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

namespace Zerolauncher.Manager
{
	enum NameSpace
	{
		Accounts,
		Groups,
		ecs,
		None
	}

	static class DataStreamNew
	{
		private const string path = "users.data";
		static byte[] key = [9, 5, 33, 64, 99, 200, 66, 77];
		static int hearder_version = 20240531;

		static void InitHandle(NameSpace ns, DataItem item)
		{
			switch (ns)
			{
				case NameSpace.Accounts:
					AccountData.Init(item);
					break;
				case NameSpace.Groups:
					GroupsData.Init(item);
					break;
			}
		}

		static DataItem[] GetAllData() { return [GroupsData.Out(), AccountData.Out()]; }

		public static void Load()
		{
			if (File.Exists(path))
			{
				byte[] byteArray;
				using (FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read))
				{
					byteArray = new byte[fs.Length];
					fs.Read(byteArray, 0, byteArray.Length);
				}
				ByteCry(byteArray);
				byteArray = Decompress(byteArray);
				{
					var data = new DataItem(NameSpace.None, byteArray);
					if (data.ReadInt() != hearder_version)
					{
						data.ReSetOffset();
						OldDataUpdate(data);
						return;
					}
					NameSpace _id;
					int _lenght;
					while (!data.IsEnd())
					{
						_id = (NameSpace)data.ReadInt();
						_lenght = data.ReadInt();

						InitHandle(_id, new DataItem(_id, data.GetBytes(_lenght)));
					}
				}
				return;

			}
			InitDefaultData();
		}

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

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

		public static void Save()
		{
			byte[] buffer;
			{
				DataItem buffers = new(NameSpace.None, []);
				buffers.WriteInt(hearder_version);
				foreach (DataItem item in GetAllData())
				{
					buffers.Write(BitConverter.GetBytes((uint)item.id));
					buffers.Write(BitConverter.GetBytes(item.value.Length));
					buffers.Write(item.value);
				}
				buffer = CompressBytes(buffers.value);
				ByteCry(buffer);
			}
			using (FileStream file = new(path, FileMode.OpenOrCreate, FileAccess.ReadWrite))
			{
				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 (MemoryStream 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();
					}
				}
			}
		}
	}

	class DataItem
	{
		public NameSpace id;
		int offset = 0;
		public byte[] value;

		public DataItem(NameSpace id, byte[] value)
		{
			this.id = id;
			this.value = value;
		}

		public bool IsEnd() { return offset >= value.Length - 1; }

		public void ReSetOffset()
		{
			offset = 0;
		}

		public byte[] GetBytes(int lenght)
		{
			offset += lenght;
			return value.Skip(offset - lenght).Take(lenght).ToArray();
		}

		public int ReadInt()
		{
			offset += 4;
			return BitConverter.ToInt32(value, offset - 4);

		}
		public String ReadStr()
		{
			int lenght = ReadInt();
			offset += lenght;
			return System.Text.Encoding.UTF8.GetString(value, offset - lenght, lenght);
		}

		public void Write(byte[] bytes)
		{
			var arr = new byte[bytes.Length + value.Length];
			Array.Copy(value, arr, value.Length);
			Array.Copy(bytes, 0, arr, value.Length, bytes.Length);
			value = arr;
		}

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

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

	public class AccountNew
	{
		public int groupId, providerId, serverId;
		public string userName, userPWD, nickName;
	}


	static class AccountData
	{
		public static int teamIndex;

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

		public static Dictionary<String, AccountNew> dict = [];

		public static void Init(DataItem data)
		{
			data.ReSetOffset();
			teamIndex = data.ReadInt();
			var accountCount = data.ReadInt();
			for (int 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)
		{
			int count = 0;
			while (dict.ContainsKey(item.nickName))
				item.nickName += count++.ToString();
			CheckGroup(item.groupId);
			data[item.groupId].Add(item);
		}

		public static bool CheckGroup(int groupId)
		{
			if (GroupsData.data.ContainsKey(groupId))
			{
				if (!data.ContainsKey(groupId)) data.Add(groupId, new List<AccountNew> { });
				return true;
			}
			return false;
		}

		public static void RemoveGroup()
		{
			GroupsData.data.Remove(teamIndex);
			foreach (var item in data[teamIndex])
			{
				dict.Remove(item.nickName);
			}
			data.Remove(teamIndex);
		}

		public static DataItem Out()
		{
			var res = new DataItem(NameSpace.Accounts, []);
			res.WriteInt(teamIndex);
			res.WriteInt(data.Count);
			foreach (var items in data.Values)
			{
				foreach (var item in items)
				{
					res.WriteInt(item.groupId);
					res.WriteInt(item.providerId);
					res.WriteInt(item.serverId);
					res.WriteString(item.userName);
					res.WriteString(item.userPWD);
					res.WriteString(item.nickName);
				}
			}
			return res;
		}
	}

	static class GroupsData
	{
		public static Dictionary<int, String> data = [];
		public static void Init(DataItem data)
		{
			int count = data.ReadInt();
			for (int i = 0; i < count; i++)
			{
				GroupsData.data.Add(data.ReadInt(), data.ReadStr());
			}
		}

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

		public static DataItem Out()
		{
			var res = new DataItem(NameSpace.Groups, []);
			res.WriteInt(data.Count);
			foreach (var item in data)
			{
				res.WriteInt(item.Key);
				res.WriteString(item.Value);
			}
			return res;
		}
	}

}
