using System.Buffers;
using System.Diagnostics;
using System.IO;
using System.IO.Compression;

namespace Zerolauncher.Manager
{

	class DiyWriteSteamer()
	{
		ArrayBufferWriter<byte> data = new();


		public void WriteInt(int value)
		{
			data.Write(BitConverter.GetBytes(value));
		}

		public void WriteString(string value)
		{
			byte[] bytes = System.Text.Encoding.UTF8.GetBytes(value);
			WriteInt(bytes.Length);
			data.Write(bytes);
		}

		public byte[] GetBytes() => data.WrittenSpan.ToArray();
	}

	class DiyReader(byte[] data, int _offset=0)
	{
		public int ReadInt()
		{
			_offset += 4;
			return BitConverter.ToInt32(data, _offset - 4);

		}
		public string ReadStr()
		{
			int lenght = ReadInt();
			_offset += lenght;
			return System.Text.Encoding.UTF8.GetString(data, _offset - lenght, lenght);
		}
	}

	internal static class DataStreamNew
	{
		private const string Path = "users.data";
		private static readonly byte[] Key = [9, 5, 33, 64, 99, 200, 66, 77];
		private const int HeaderVersion = 20240531;

		public static void Load()
		{
			if (File.Exists(Path))
			{
				byte[] byteArray;
				using (var fs = new FileStream(Path, FileMode.Open, FileAccess.Read))
				{
					byteArray = new byte[fs.Length];
					fs.ReadExactly(byteArray, 0, byteArray.Length);
				}

				ByteCry(byteArray);
				byteArray = Decompress(byteArray);
				{
					var data = new DiyReader(byteArray);
					if (data.ReadInt() != HeaderVersion)
					{
						OldDataUpdate(data);
						return;
					}
					GroupsData.Init(data);
					AccountData.Init(data);
				}
				return;

			}
			InitDefaultData();
		}

		static void OldDataUpdate(DiyReader _item)
		{
			InitDefaultData();
		}

		static void InitDefaultData()
		{
			Trace.WriteLine("加载初始数据");
			GroupsData.InitDefaultData();
			AccountData.InitDefaultData();
		}

		public static void Save()
		{
			var data = new DiyWriteSteamer();
			
			data.WriteInt(HeaderVersion);
			GroupsData.Out(data);
			AccountData.Out(data);

			var buffer = CompressBytes(data.GetBytes());
			ByteCry(buffer);


			using (FileStream file = new(Path, FileMode.OpenOrCreate, FileAccess.ReadWrite))
			{
				file.Seek(0, SeekOrigin.Begin);
				file.Write(buffer);
			}
		}


		static void ByteCry(byte[] data)
		{
			for (int i = 0; i < data.Length; i++)
			{
				data[i] = (byte)(data[i] ^ Key[i % Key.Length]);
			}
		}

		//压缩字节
		//1.创建压缩的数据流 
		//2.设定compressStream为存放被压缩的文件流,并设定为压缩模式
		//3.将需要压缩的字节写到被压缩的文件流
		static byte[] CompressBytes(byte[] bytes)
		{
			using var compressStream = new MemoryStream();
			using (var zipStream = new GZipStream(compressStream, CompressionMode.Compress))
				zipStream.Write(bytes, 0, bytes.Length);
			return compressStream.ToArray();
		}

		//解压缩字节
		//1.创建被压缩的数据流
		//2.创建zipStream对象，并传入解压的文件流
		//3.创建目标流
		//4.zipStream拷贝到目标流
		//5.返回目标流输出字节
		static byte[] Decompress(byte[] bytes)
		{
			using (var compressStream = new MemoryStream(bytes))
			{
				using (var zipStream = new GZipStream(compressStream, CompressionMode.Decompress))
				{
					using (var resultStream = new MemoryStream())
					{
						zipStream.CopyTo(resultStream);
						return resultStream.ToArray();
					}
				}
			}
		}
	}



	public class AccountNew
	{
		public int GroupId, ProviderId, ServerId;
		public string userName, userPWD, nickName;
	}


	internal static class AccountData
	{
		public static int TeamIndex = 0;

		public static readonly Dictionary<int, List<AccountNew>> Data = [];

		public static readonly Dictionary<string, AccountNew> Dict = [];

		public static void Init(DiyReader data)
		{
			TeamIndex = data.ReadInt();
			var accountCount = data.ReadInt();
			for (var i = 0; i < accountCount; i++)
			{
				AddAccount(new AccountNew()
				{
					GroupId = data.ReadInt(),
					ProviderId = data.ReadInt(),
					ServerId = data.ReadInt(),
					userName = data.ReadStr(),
					userPWD = data.ReadStr(),
					nickName = data.ReadStr()
				});
			}
		}

		public static void InitDefaultData()
		{
			AddAccount(new AccountNew()
			{
				GroupId = 0,
				ProviderId = 0,
				ServerId = 1,
				userName = "test",
				userPWD = "test",
				nickName = "右键修改账号"
			});
		}

		public static void AddAccount(AccountNew item)
		{
			var count = 0;
			while (Dict.ContainsKey(item.nickName))
				item.nickName += count++.ToString();
			if (CheckGroup(item.GroupId))
				Data[item.GroupId].Add(item);
		}

		public static bool CheckGroup(int groupId)
		{
			if (!GroupsData.Data.ContainsKey(groupId)) return false;
			if (!Data.ContainsKey(groupId)) Data.Add(groupId, []);
			return true;
		}

		public static void RemoveGroup()
		{
			GroupsData.Data.Remove(TeamIndex);
			foreach (var item in Data[TeamIndex])
			{
				Dict.Remove(item.nickName);
			}
			Data.Remove(TeamIndex);
		}

		public static void Out(DiyWriteSteamer data)
		{
			data.WriteInt(TeamIndex);
			
			var arr = new List<AccountNew>();
			foreach (var item in Data.Values)
				arr.AddRange(item);
			data.WriteInt(arr.Count);
			foreach (var item in arr)
			{
				data.WriteInt(item.GroupId);
				data.WriteInt(item.ProviderId);
				data.WriteInt(item.ServerId);
				data.WriteString(item.userName);
				data.WriteString(item.userPWD);
				data.WriteString(item.nickName);
			}
		}
	}

	internal static class GroupsData
	{
		public static readonly Dictionary<int, string> Data = [];
		public static void Init(DiyReader dataItem)
		{
			var count = dataItem.ReadInt();
			for (var i = 0; i < count; i++)
			{
				Data.Add(dataItem.ReadInt(), dataItem.ReadStr());
			}
		}

		public static void InitDefaultData()
		{
			Data.Add(0, "队伍1");
		}

		public static void Out(DiyWriteSteamer data)
		{
			data.WriteInt(Data.Count);
			foreach (var item in Data)
			{
				data.WriteInt(item.Key);
				data.WriteString(item.Value);
			}
		}
	}

}
