using System;
using System.Collections.Generic;
using System.IO;
using System.Text.Json;

namespace Crysome.Server.Data;

public class AppDataStore
{
	private static readonly string DataDir = AppDomain.CurrentDomain.BaseDirectory;

	public ServerSettings Settings { get; set; } = new ServerSettings();

	public Dictionary<string, string> Notes { get; set; } = new Dictionary<string, string>();

	public HashSet<string> PinnedIPs { get; set; } = new HashSet<string>();

	public HashSet<string> AnnounceIPs { get; set; } = new HashSet<string>();

	public HashSet<string> BlockedIPs { get; set; } = new HashSet<string>();

	public Dictionary<string, DateTime> MutedIPs { get; set; } = new Dictionary<string, DateTime>();

	public Dictionary<string, string> Snippets { get; set; } = new Dictionary<string, string>();

	public List<AutoTask> AutoTasks { get; set; } = new List<AutoTask>();

	public Dictionary<string, bool> ContextMenuFeatures { get; set; } = new Dictionary<string, bool>();

	public List<StoredClientRecord> Clients { get; private set; } = new List<StoredClientRecord>();

	public void Load()
	{
		Settings = LoadServerSettings() ?? new ServerSettings();
		Notes = LoadFile<Dictionary<string, string>>("notes.json") ?? new Dictionary<string, string>();
		PinnedIPs = LoadFile<HashSet<string>>("pinned.json") ?? new HashSet<string>();
		AnnounceIPs = LoadFile<HashSet<string>>("announce.json") ?? new HashSet<string>();
		BlockedIPs = LoadFile<HashSet<string>>("blocked.json") ?? new HashSet<string>();
		MutedIPs = LoadFile<Dictionary<string, DateTime>>("muted.json") ?? new Dictionary<string, DateTime>();
		Snippets = LoadFile<Dictionary<string, string>>("snippets.json") ?? new Dictionary<string, string>();
		AutoTasks = LoadFile<List<AutoTask>>("autotasks.json") ?? new List<AutoTask>();
		ContextMenuFeatures = LoadFile<Dictionary<string, bool>>("contextmenu_features.json") ?? new Dictionary<string, bool>();
		Clients = LoadFile<List<StoredClientRecord>>("clients.json") ?? new List<StoredClientRecord>();
		List<string> list = new List<string>();
		foreach (KeyValuePair<string, DateTime> mutedIP in MutedIPs)
		{
			if (mutedIP.Value <= DateTime.Now)
			{
				list.Add(mutedIP.Key);
			}
		}
		foreach (string item in list)
		{
			MutedIPs.Remove(item);
		}
	}

	public void SaveSettings()
	{
		SaveFile("settings.json", Settings);
	}

	public void SaveNotes()
	{
		SaveFile("notes.json", Notes);
	}

	public void SavePinned()
	{
		SaveFile("pinned.json", PinnedIPs);
	}

	public void SaveAnnounce()
	{
		SaveFile("announce.json", AnnounceIPs);
	}

	public void SaveBlocked()
	{
		SaveFile("blocked.json", BlockedIPs);
	}

	public void SaveMuted()
	{
		SaveFile("muted.json", MutedIPs);
	}

	public void SaveSnippets()
	{
		SaveFile("snippets.json", Snippets);
	}

	public void SaveAutoTasks()
	{
		SaveFile("autotasks.json", AutoTasks);
	}

	public void SaveContextMenuFeatures()
	{
		SaveFile("contextmenu_features.json", ContextMenuFeatures);
	}

	public void SaveClients()
	{
		SaveFile("clients.json", Clients);
	}

	public void SaveAll()
	{
		SaveSettings();
		SaveNotes();
		SavePinned();
		SaveAnnounce();
		SaveBlocked();
		SaveMuted();
		SaveSnippets();
		SaveAutoTasks();
		SaveContextMenuFeatures();
		SaveClients();
	}

	public void UpsertClient(StoredClientRecord rec)
	{
		if (rec != null && !string.IsNullOrEmpty(rec.Address))
		{
			StoredClientRecord storedClientRecord = Clients.Find((StoredClientRecord c) => c.Address == rec.Address);
			if (storedClientRecord != null)
			{
				Clients.Remove(storedClientRecord);
			}
			Clients.Insert(0, rec);
			if (Clients.Count > 2000)
			{
				Clients.RemoveRange(2000, Clients.Count - 2000);
			}
		}
	}

	public StoredClientRecord FindClient(string address)
	{
		return Clients.Find((StoredClientRecord c) => string.Equals(c.Address, address, StringComparison.OrdinalIgnoreCase));
	}

	public bool IsContextMenuFeatureEnabled(string key)
	{
		if (!ContextMenuFeatures.TryGetValue(key, out var value))
		{
			return true;
		}
		return value;
	}

	private ServerSettings LoadServerSettings()
	{
		try
		{
			string path = Path.Combine(DataDir, "settings.json");
			if (!File.Exists(path))
			{
				return null;
			}
			string json = File.ReadAllText(path);
			using JsonDocument jsonDocument = JsonDocument.Parse(json);
			JsonElement rootElement = jsonDocument.RootElement;
			JsonElement value;
			bool flag = rootElement.TryGetProperty("LegacyUdpPort", out value);
			bool flag2 = rootElement.TryGetProperty("QuicPort", out value);
			ServerSettings serverSettings = JsonSerializer.Deserialize<ServerSettings>(json);
			if (serverSettings == null)
			{
				return new ServerSettings();
			}
			if (flag && !flag2)
			{
				JsonElement value2;
				int quicPort = (rootElement.TryGetProperty("Port", out value2) ? value2.GetInt32() : 7777);
				JsonElement value3;
				int port = (rootElement.TryGetProperty("LegacyUdpPort", out value3) ? value3.GetInt32() : 7778);
				serverSettings.Port = port;
				serverSettings.QuicPort = quicPort;
			}
			return serverSettings;
		}
		catch
		{
			return null;
		}
	}

	private T LoadFile<T>(string filename) where T : class
	{
		try
		{
			string path = Path.Combine(DataDir, filename);
			if (!File.Exists(path))
			{
				return null;
			}
			return JsonSerializer.Deserialize<T>(File.ReadAllText(path));
		}
		catch
		{
			return null;
		}
	}

	private void SaveFile<T>(string filename, T data)
	{
		try
		{
			string path = Path.Combine(DataDir, filename);
			JsonSerializerOptions options = new JsonSerializerOptions
			{
				WriteIndented = true
			};
			File.WriteAllText(path, JsonSerializer.Serialize(data, options));
		}
		catch
		{
		}
	}
}
