using System.Text.Json;

namespace RobotNet.RobotManager.Services.OpenACS;

public class OpenACSManager : BackgroundService
{
    public bool TrafficEnable => Config.TrafficEnable;
    public string TrafficURL => Config.TrafficURL ?? "";
    public string[] TrafficURLUsed => [..Config.TrafficURLUsed ?? []];
    public bool PublishEnable => Config.PublishEnable;
    public string PublishURL => Config.PublishURL ?? "";
    public string[] PublishURLUsed => [..Config.PublishURLUsed ?? []];
    public int PublishInterval => Config.PublishInterval;
    public event Action? PublishIntervalChanged;

    private ConfigData Config;
    private const string DataPath = "openACSConfig.json";
    private struct ConfigData
    {
        public string PublishURL { get; set; }
        public List<string> PublishURLUsed { get; set; } 
        public bool PublishEnable { get; set; }
        public string TrafficURL { get; set; }
        public List<string> TrafficURLUsed { get; set; }
        public bool TrafficEnable { get; set; }
        public int PublishInterval { get; set; }
    }

    public async Task UpdateTrafficURL(string url)
    {
        if (url == Config.TrafficURL) return;

        Config.TrafficURL = url;
        Config.TrafficURLUsed ??= [];
        var urlUsed = Config.TrafficURLUsed.FirstOrDefault(u => u.Equals(url, StringComparison.CurrentCultureIgnoreCase));
        if (urlUsed is not null)
        {
            Config.TrafficURLUsed.Remove(urlUsed);
        }
        else if (Config.PublishURLUsed.Count >= 10) Config.TrafficURLUsed.Remove(Config.TrafficURLUsed.Last());
        Config.TrafficURLUsed.Insert(0, url);
        await File.WriteAllTextAsync(DataPath, JsonSerializer.Serialize(Config));
    }

    public async Task UpdateTrafficEnable(bool enable)
    {
        if (enable == Config.TrafficEnable) return;

        Config.TrafficEnable = enable;
        await File.WriteAllTextAsync(DataPath, JsonSerializer.Serialize(Config));
    }

    public async Task UpdatePublishURL(string url)
    {
        if (url == Config.PublishURL) return;

        Config.PublishURL = url;
        Config.PublishURLUsed ??= [];
        var urlUsed = Config.PublishURLUsed.FirstOrDefault(u => u.Equals(url, StringComparison.OrdinalIgnoreCase));
        if (urlUsed is not null)
        {
            Config.PublishURLUsed.Remove(urlUsed);
        }
        else if (Config.PublishURLUsed.Count >= 10) Config.PublishURLUsed.Remove(Config.PublishURLUsed.Last());
        Config.PublishURLUsed.Insert(0, url);
        await File.WriteAllTextAsync(DataPath, JsonSerializer.Serialize(Config));
    }

    public async Task UpdatePublishEnable(bool enable)
    {
        if (enable == Config.PublishEnable) return;

        Config.PublishEnable = enable;
        await File.WriteAllTextAsync(DataPath, JsonSerializer.Serialize(Config));
    }

    public async Task UpdatePublishInterval(int interval)
    {
        if (interval == Config.PublishInterval) return;

        Config.PublishInterval = interval;
        PublishIntervalChanged?.Invoke();
        await File.WriteAllTextAsync(DataPath, JsonSerializer.Serialize(Config));
    }

    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        if (File.Exists(DataPath))
        {
            try
            {
                Config = JsonSerializer.Deserialize<ConfigData>(await File.ReadAllTextAsync(DataPath, CancellationToken.None));
                PublishIntervalChanged?.Invoke();
            }
            catch (JsonException)
            {
                await File.WriteAllTextAsync(DataPath, JsonSerializer.Serialize(Config), CancellationToken.None);
            }
        }
        else await File.WriteAllTextAsync(DataPath, JsonSerializer.Serialize(Config), CancellationToken.None);
    }
}
