using System;
using System.Diagnostics;
using System.Net;
using System.Threading;

namespace ETDiscordPresence
{
	internal class GameWatcher : IDisposable
	{
		internal delegate void EnterServerDelegate(ServerInfo serverInfo);

		internal delegate void LeaveServerDelegate();

		internal EnterServerDelegate EnterServer;

		internal LeaveServerDelegate LeaveServer;

		private Thread thread;

		private GameReader activeReader;

		private ServerInfo? activeServerInfo;

		internal void Start()
		{
			if (thread != null)
			{
				return;
			}
			
			thread = new Thread(() =>
			{
				try
				{
					for (;;)
					{
						if (activeReader != null)
						{
							UpdateServerInfo(activeReader);
						}

						if (activeReader == null)
						{
							FindGame();
						}

						Thread.Sleep(15000);
					}
				}
				catch (ThreadAbortException)
				{
				}
			});
			
			thread.Start();
		}

		private void FindGame()
		{
			foreach (var process in Process.GetProcessesByName("et"))
			{
				UpdateServerInfo(new GameReader(process));

				if (activeReader != null)
				{
					break;
				}
			}
		}

		private void UpdateServerInfo(GameReader reader)
		{
			var info = reader.Read();

			if (activeReader == null && info.HasValue)
			{
				activeReader = reader;
			}
			else if (!info.HasValue)
			{
				reader.Dispose();
				activeReader = null;

				if (!activeServerInfo.HasValue)
				{
					return;
				}

				activeServerInfo = null;
				LeaveServer();

				return;
			}

			if (activeServerInfo.HasValue &&
			    activeServerInfo.Value.Hostname == info.Value.Hostname &&
			    activeServerInfo.Value.Address == info.Value.Address)
			{
				return;
			}

			activeServerInfo = info;
			EnterServer(activeServerInfo.Value);
		}

		internal struct ServerInfo
		{
			public string Address;
			public string Hostname;
		}

		public void Dispose()
		{
			thread?.Abort();
		}
	}
}