using System;
using System.Collections.Generic;
using System.Text;
using System.Diagnostics;

using Microsoft.Win32;

namespace EA.GameTalkMessages
{
	public class Configuration
	{
		public const string RunServerAsAppCommandLineArgs = "-RunServerAsApp";

		#region Singleton code
		public static Configuration Instance
		{
			get { return Nested.instance; }
		}

		class Nested
		{
			static Nested() { }
			internal static readonly Configuration instance = new Configuration();
		}
		#endregion

		public string GetInstalledGameTalkVersion()
		{
			return RegistrySettings.GetString("Version");
		}

		public bool SetInstalledGameTalkVersion(string version, bool runningAsApp)
		{
			if (RegistrySettings.SetValue("Version", version))
			{
				bool setVersionIn32BitArea = true;
				if (IntPtr.Size == 8) // Check that this is a 64 bit application (only time we need to do this - to accomodate 32 bit apps running on a Vista 64 machine)
				{
					// Hack because on Vista 64 - 32 bit applications will read/write to a Wow6432Node location in the registry - that is, if we're a 64 bit GameTalk app - we'll need to inform all 32 bit GameTalk apps (running on this 64 bit OS) the version of GameTalk we've installed
					// Note: this RegistryKey virtualization/redirection only happens for LocalMachine - not CurrentUser - i.e. setting the value in the 32 bit area is only necessary when the user is running the GameTalkServer as a service - however, MS could change that at anytime - so we'll continue to do this
					setVersionIn32BitArea = RegistrySettings.SetValueIn32Bit("Version", version);
				}

				// It is probably safe to stop doing this - since 1.9.1 is over five years old.  It should be sufficient for users of that tech to either upgrade or use the work-around of making the start-up order of their GameTalk applications "pre 1.9.1 application first"
				// The main reason I want to stop doing this is because if the user uses the stand-alone GameTalkServer (instead of as a service) we'll stomp over the version

				/*// The following is added to address a bug in an old version of GameTalk (that was fixed in 1.9.1) - that is the "is this version greater" check had a flaw
				// that would result in an older version getting installed over a newer version.  This also prevents the situation where a user has never run any tool that uses
				// GameTalk, then runs a GameTalk 2.0 tool, then runs a GameTalk 1.8 tool - in this situation the 1.8 tool wouldn't know wouldn't be able to find a version value to
				// compare with - because the location has changed
				bool setVersionInUserRegion = true;
				if (!runningAsApp)
					setVersionInUserRegion = RegistrySettings.SetValueInUserRegion("Version", "1.9.9.9");

				return setVersionIn32BitArea && setVersionInUserRegion;*/
				return setVersionIn32BitArea;
			}
			return false;
		}

		public int GetGameTalkServerPortNum()
		{
			return RegistrySettings.GetInt32("Port");
		}

		public bool SetGameTalkServerPortNum(int portNum)
		{
			if (RegistrySettings.SetValue("Port", portNum))
			{
				if (IntPtr.Size == 8) // Check that this is a 64 bit application (only time we need to do this - to accomodate 32 bit apps running on a Vista 64 machine)
				{
					// Hack because on Vista 64 - 32 bit applications will read/write to a Wow6432Node location in the registry
					return RegistrySettings.SetValueIn32Bit("Port", portNum);
				}
				else
					return true;
			}

			return false;
		}

		public LoggingLevel GetLoggingLevel()
		{
			byte[] parseMsgContentsBytes = RegistrySettings.GetBytes("ParseMessageContents");
			if ((parseMsgContentsBytes != null) && (parseMsgContentsBytes.Length > 0))
				return (LoggingLevel)parseMsgContentsBytes[0];
			else
				return LoggingLevel.META_DATA;
		}

		public bool SetLoggingLevel(LoggingLevel loggingLevel)
		{
			return RegistrySettings.SetByte("ParseMessageContents", (byte)loggingLevel);
		}

		public bool LimitLogFileSize()
		{
			byte[] limitLogFileSizeBytes = RegistrySettings.GetBytes("LimitLogFileSize");
			if ((limitLogFileSizeBytes != null) && (limitLogFileSizeBytes.Length > 0) && (limitLogFileSizeBytes[0] == 0))
				return false;
			else
				return true;
		}

		public bool SetLimitOnLogFileSize(bool limit)
		{
			return RegistrySettings.SetByte("LimitLogFileSize", (limit) ? (byte)1 : (byte)0);
		}

		public byte[] GetPassPhraseKey()
		{
			return RegistrySettings.GetBytes("Passphrase");
		}

		public Target[] GetRegisteredTargets(int defaultPort)
		{
			return RegistrySettings.GetRegisteredTargets(defaultPort);
		}

		public Target GetRegisteredTarget(string targetName, int defaultPort)
		{
			return RegistrySettings.GetRegisteredTarget(targetName, defaultPort);
		}

		public bool AddOrUpdateRegisteredTarget(Target target)
		{
			return RegistrySettings.RegisterTarget(target);
		}

		public bool CheckNetworkConnectivity()
		{
			try
			{
				object checkNetworkConnectivityObj = RegistrySettings.GetValue("CheckNetworkConnectivity");
				if (checkNetworkConnectivityObj == null)
					return false;
				else
				{
					if (checkNetworkConnectivityObj is bool)
					{
						bool checkNetworkConnectivity = (bool)checkNetworkConnectivityObj;
						return checkNetworkConnectivity;
					}
					else
						return false;
				}
			}
			catch
			{
				return false;				
			}
		}

		public void SetCheckNetworkConnectivity(bool checkNetworkConnectivity)
		{
			try
			{
				RegistrySettings.SetValue("CheckNetworkConnectivity", checkNetworkConnectivity);
			}
			catch
			{
			}
		}

		public bool Use32BitGameTalkServer
		{
			get
			{
				try
				{
					object use32BitGameTalkServerObj = RegistrySettings.GetValue("Use32BitGameTalkServer");
					if (use32BitGameTalkServerObj == null)
						return false;
					else
					{
						bool boolResult = false;
						if (bool.TryParse((string)use32BitGameTalkServerObj, out boolResult))
							return boolResult;
						else if (use32BitGameTalkServerObj is bool)
							return (bool)use32BitGameTalkServerObj;
						else
							return false;
					}
				}
				catch
				{
					return false;
				}
			}
			set
			{
				try
				{
					// We could optionally just delete the key if (value == false)
					RegistrySettings.SetValue("Use32BitGameTalkServer", (bool)value);
				}
				catch
				{
				}
			}
		}

		public bool UseNamedPipes
		{
			get
			{
				try
				{
					object useNamedPipesObj = RegistrySettings.GetValue("UseNamedPipes");
					if (useNamedPipesObj == null)
						return false;
					else
					{
						bool boolResult = false;
						if (bool.TryParse((string)useNamedPipesObj, out boolResult))
							return boolResult;
						else if (useNamedPipesObj is bool)
							return (bool)useNamedPipesObj;
						else
							return false;
					}
				}
				catch
				{
					return false;
				}
			}
			set
			{
				try
				{
					// We could optionally just delete the key if (value == false)
					RegistrySettings.SetValue("UseNamedPipes", (bool)value);
				}
				catch
				{
				}
			}
		}

		/// <summary>
		/// This could probably reference the GetInstalledGameTalkVersion
		/// </summary>
		/// <param name="fileTalkRegEntry"></param>
		/// <returns></returns>
		public string GetInstalledFileTalkVersion(string fileTalkRegEntry)
		{
			RegistryKey fileTalkRegKey = null;
			try
			{
				fileTalkRegKey = RegistrySettings.RegistryKeyArea.OpenSubKey(fileTalkRegEntry);
				return (string)fileTalkRegKey.GetValue("Version");
			}
			catch { }
			finally
			{
				if (fileTalkRegKey != null)
					fileTalkRegKey.Close();
			}
			return null;
		}

		/// <summary>
		/// This could probably reference the SetInstalledGameTalkVersion
		/// </summary>
		/// <param name="fileTalkRegEntry"></param>
		/// <param name="version"></param>
		/// <returns></returns>
		public bool SetInstalledFileTalkVersion(string fileTalkRegEntry, string version)
		{
			RegistryKey fileTalkRegKey = null;
			try
			{
				fileTalkRegKey = RegistrySettings.RegistryKeyArea.CreateSubKey(fileTalkRegEntry);
				fileTalkRegKey.SetValue("Version", version);
			}
			catch
			{
				return false;
			}
			finally
			{
				if (fileTalkRegKey != null)
					fileTalkRegKey.Close();
			}
			return true;
		}

		public Process GameTalkServerRunningAsApplication()
		{
			string gameTalkServerInLowerCase = GameTalkMessage.sGameTalkServerID.ToLower();
			foreach (Process clsProcess in Process.GetProcesses())
			{
				if (clsProcess.ProcessName.ToLower().Contains(gameTalkServerInLowerCase))
				{
					return clsProcess;
				}
			}
			return null;
		}
	}
}
