using System;
using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;
using Munga.Net;

namespace TeslaConsole;

public class MungaGame
{
	private readonly object mInternalLock = new object();

	private readonly Pod mPod;

	private Image mImage;

	private string mStatusMessage;

	private MungaSocket mSocket;

	private DateTime mNextStateQuery = DateTime.MinValue;

	private ApplicationState? mAppState;

	private ApplicationID? mAppID;

	private DateTime mEggDelayTimer = DateTime.MinValue;

	private DateTime mEggSent = DateTime.MinValue;

	private bool mEggAck;

	private MungaConnectionState mState;

	private readonly List<object> mRequestors = new List<object>();

	private Form mOwner;

	public Image Image => mImage;

	public string StatusMessage => mStatusMessage;

	public Pod Pod => mPod;

	public ApplicationState? AppState => mAppState;

	public ApplicationID? AppID => mAppID;

	public DateTime EggDelayTimer
	{
		get
		{
			return mEggDelayTimer;
		}
		set
		{
			mEggDelayTimer = value;
		}
	}

	public DateTime EggSent
	{
		get
		{
			return mEggSent;
		}
		set
		{
			mEggSent = value;
		}
	}

	public bool EggAcknowledged => mEggAck;

	public MungaConnectionState State
	{
		get
		{
			lock (mInternalLock)
			{
				if (mState == MungaConnectionState.Connected)
				{
					if (mSocket != null && mSocket.Connected)
					{
						return MungaConnectionState.Connected;
					}
					Disconnect();
				}
				return mState;
			}
		}
		private set
		{
			lock (mInternalLock)
			{
				mState = value;
			}
		}
	}

	public bool Requested
	{
		get
		{
			lock (mInternalLock)
			{
				return mRequestors.Count > 0;
			}
		}
	}

	public bool IsOwned
	{
		get
		{
			if (mOwner != null && mOwner.IsDisposed)
			{
				mOwner = null;
			}
			return mOwner != null;
		}
	}

	public event EventHandler OnPodStatusUpdated;

	public void QueryStateIfNeeded()
	{
		DateTime now = DateTime.Now;
		if (mNextStateQuery < now)
		{
			Send(0, 1, new StateQueryMessage(1));
			mNextStateQuery = now.AddSeconds(1.0);
		}
	}

	public bool IsPodAppState(ApplicationID app, ApplicationState state)
	{
		return IsPodAppState(app, new ApplicationState[1] { state });
	}

	public bool IsPodAppState(ApplicationID app, IEnumerable<ApplicationState> states)
	{
		if (IsPodOperational(app))
		{
			foreach (ApplicationState state in states)
			{
				if (mAppState.Value == state)
				{
					return true;
				}
			}
		}
		return false;
	}

	public bool IsPodOperational(ApplicationID app)
	{
		if (State == MungaConnectionState.Connected && mAppID.HasValue && mAppID.Value == app)
		{
			return mAppState.HasValue;
		}
		return false;
	}

	public void MakeRequested(object requestor)
	{
		lock (mInternalLock)
		{
			if (!mRequestors.Contains(requestor))
			{
				mRequestors.Add(requestor);
				if (mRequestors.Count == 1)
				{
					Connect();
				}
			}
		}
	}

	public void ReleaseRequest(object requestor)
	{
		lock (mInternalLock)
		{
			if (mRequestors.Contains(requestor))
			{
				mRequestors.Remove(requestor);
				if (mRequestors.Count == 0)
				{
					Disconnect();
				}
			}
		}
	}

	public bool IsOwner(Form owner)
	{
		if (mOwner != null && mOwner.IsDisposed)
		{
			mOwner = null;
		}
		return mOwner == owner;
	}

	public void TakeOwnership(Form owner)
	{
		lock (mInternalLock)
		{
			if (mOwner == null)
			{
				mOwner = owner;
				ForceStatusUpdate();
			}
		}
	}

	public void ReleaseOwnership(Form owner)
	{
		lock (mInternalLock)
		{
			if (mOwner == owner)
			{
				mOwner = null;
				ForceStatusUpdate();
			}
		}
	}

	public MungaGame(Pod pod)
	{
		mPod = pod;
	}

	public void SetStatus(Image img, string statusMessage)
	{
		lock (mInternalLock)
		{
			if (mImage != img || mStatusMessage != statusMessage)
			{
				mImage = img;
				mStatusMessage = statusMessage;
				ForceStatusUpdate();
			}
		}
	}

	private void ForceStatusUpdate()
	{
		if (this.OnPodStatusUpdated != null)
		{
			this.OnPodStatusUpdated(this, EventArgs.Empty);
		}
	}

	private void Connect()
	{
		lock (mInternalLock)
		{
			if (State != 0)
			{
				return;
			}
			State = MungaConnectionState.Connecting;
			ShutdownSocket();
			mSocket = new MungaSocket();
			mSocket.BeginConnect(mPod.IPAddress, 1501, delegate(IAsyncResult ar)
			{
				lock (mInternalLock)
				{
					try
					{
						mSocket.EndConnect(ar);
						State = MungaConnectionState.Connected;
					}
					catch
					{
						Disconnect();
					}
				}
			}, null);
		}
	}

	private void Disconnect()
	{
		lock (mInternalLock)
		{
			State = MungaConnectionState.Disconnected;
			mAppState = null;
			mAppID = null;
			mNextStateQuery = DateTime.MinValue;
			ShutdownSocket();
			if (Requested)
			{
				Connect();
			}
		}
	}

	private void ShutdownSocket()
	{
		if (mSocket != null)
		{
			try
			{
				mSocket.Shutdown();
			}
			catch
			{
			}
			mSocket = null;
		}
	}

	public MetaMessage Receive()
	{
		lock (mInternalLock)
		{
			try
			{
				MetaMessage metaMessage = mSocket.Receive();
				if (metaMessage != null)
				{
					if (metaMessage.Message is StateResponseMessage)
					{
						StateResponseMessage stateResponseMessage = (StateResponseMessage)metaMessage.Message;
						mAppID = stateResponseMessage.Application;
						if (stateResponseMessage.ApplicationState == ApplicationState.WaitingForEgg && stateResponseMessage.ApplicationState != mAppState)
						{
							mEggDelayTimer = DateTime.Now.AddSeconds(5.0);
							mEggSent = DateTime.MinValue;
							mEggAck = false;
						}
						mAppState = stateResponseMessage.ApplicationState;
					}
					else if (metaMessage.Message is AcknowledgeEggFileMessage)
					{
						mEggAck = true;
					}
				}
				return metaMessage;
			}
			catch
			{
				Disconnect();
				return null;
			}
		}
	}

	public void Send(int gameID, int fromHost, MungaMessage message)
	{
		lock (mInternalLock)
		{
			try
			{
				mSocket.Send(gameID, fromHost, message);
			}
			catch
			{
				Disconnect();
			}
		}
	}
}
