using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using EA.GameTalkRouter;

namespace EA.GameTalkServer
{
	class PluginManager
	{
		private static readonly PluginManager sInstance = new PluginManager();

		List<IGameTalkService> mGameTalkServices = new List<IGameTalkService>();

		public IEnumerable<IGameTalkService> GameTalkServices
		{
			get { return mGameTalkServices; }
		}

		private PluginManager()
		{
		}

		public static PluginManager Instance
		{
			get { return sInstance; }
		}

		public void LoadServices()
		{
			string executingAssemblyPath = System.Reflection.Assembly.GetExecutingAssembly().Location;
			System.IO.FileInfo gameTalkServerFileInfo = new System.IO.FileInfo(executingAssemblyPath);
			string executingAssemblyDir = gameTalkServerFileInfo.Directory.FullName;
			string pluginsDir = System.IO.Path.Combine(executingAssemblyDir, "plugins");
			System.IO.DirectoryInfo dirInfo = new System.IO.DirectoryInfo(pluginsDir);
			if (dirInfo.Exists)
			{
				Logger.LogCommentMessage("Going to try to load plugins from dir: " + dirInfo.FullName);
				System.IO.FileInfo[] fileInfos = dirInfo.GetFiles("*.dll");
				LoadAllPluginAssemblies(fileInfos);
				LoadGameTalkServices(fileInfos);
			}
		}

		private void LoadAllPluginAssemblies(System.IO.FileInfo[] dllFiles)
		{
			try
			{
				foreach (System.IO.FileInfo dllFile in dllFiles)
				{
					try
					{
						System.Reflection.Assembly assembly = System.Reflection.Assembly.LoadFrom(dllFile.FullName);
					}
					catch (Exception exception)
					{
						// Probably just means this isn't a managed dll - hence - I don't care - unless it is USBSockets
						if (dllFile.FullName.ToLower().Contains("usbsocket"))
						{
							Logger.LogCommentMessage("Wasn't able to load " + dllFile.FullName + ".  This is very likely caused by the fact your GameTalkServer needs to be a 32 bit process");
							if (exception.InnerException != null)
								Logger.LogCommentMessage("exception: " + exception.InnerException.Message + Environment.NewLine + exception.InnerException.StackTrace);
							else
								Logger.LogCommentMessage("exception: " + exception.Message);
						}
					}
				}
			}
			catch
			{

			}
		}

		private void LoadGameTalkServices(System.IO.FileInfo[] dllFiles)
		{
			string fullInterfaceName = typeof(IGameTalkService).FullName;
			foreach (System.IO.FileInfo dllFile in dllFiles)
			{
				try
				{
					System.Reflection.Assembly assembly = System.Reflection.Assembly.LoadFrom(dllFile.FullName);
					foreach (System.Type type in assembly.GetTypes())
					{
						if (type.GetInterface(fullInterfaceName) != null)
						{
							System.Diagnostics.Trace.WriteLine("Found a IGameTalkService type: " + type);
							try
							{
								object gameTalkServiceObj = assembly.CreateInstance(type.FullName);
								IGameTalkService gameTalkService = gameTalkServiceObj as IGameTalkService;
								if (gameTalkService != null)
								{
									Logger.LogCommentMessage("Successfully loaded IGameTalkService: " + type+"!");
									mGameTalkServices.Add(gameTalkService);
								}
							}
							catch (Exception exception)
							{
								if (exception.InnerException != null)
								{
									System.Diagnostics.Trace.WriteLine("exception: " + exception.InnerException.Message + Environment.NewLine + exception.InnerException.StackTrace);
								}
								else
									System.Diagnostics.Trace.WriteLine("exception: " + exception.Message);
							}
						}
					}
				}
				catch
				{
					// Probably just means this isn't a managed dll - hence - I don't care
				}
			}
		}
	}
}
