using FastGithub.Configuration;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Text.Json;
using System.Threading;
using System.Threading.Tasks;
namespace FastGithub.DomainResolve
{
    /// 
    /// 域名的IP测速服务
    /// 
    sealed class DomainSpeedTester
    {
        private const string DOMAINS_JSON_FILE = "domains.json";
        private readonly DnsClient dnsClient;
        private readonly ILogger logger;
        private readonly object syncRoot = new();
        private readonly Dictionary domainIPAddressHashSet = new();
        /// 
        /// 域名的IP测速服务
        /// 
        /// 
        /// 
        public DomainSpeedTester(
            DnsClient dnsClient,
            ILogger logger)
        {
            this.dnsClient = dnsClient;
            this.logger = logger;
            try
            {
                this.LoadDomains();
            }
            catch (Exception ex)
            {
                logger.LogWarning($"加载域名数据失败:{ex.Message}");
            }
        }
        /// 
        /// 加载域名数据
        ///  
        private void LoadDomains()
        {
            if (File.Exists(DOMAINS_JSON_FILE) == false)
            {
                return;
            }
            var utf8Json = File.ReadAllBytes(DOMAINS_JSON_FILE);
            var domains = JsonSerializer.Deserialize(utf8Json);
            if (domains == null)
            {
                return;
            }
            foreach (var domain in domains)
            {
                this.domainIPAddressHashSet.TryAdd(domain, new IPAddressItemHashSet());
            }
        }
        /// 
        /// 添加要测速的域名
        /// 
        /// 
        public void Add(string domain)
        {
            lock (this.syncRoot)
            {
                if (this.domainIPAddressHashSet.TryAdd(domain, new IPAddressItemHashSet()))
                {
                    try
                    {
                        this.SaveDomains();
                    }
                    catch (Exception ex)
                    {
                        logger.LogWarning($"保存域名数据失败:{ex.Message}");
                    }
                }
            }
        }
        /// 
        /// 保存域名
        /// 
        private void SaveDomains()
        {
            var domains = this.domainIPAddressHashSet.Keys
                .Select(item => new DomainPattern(item))
                .OrderBy(item => item)
                .Select(item => item.ToString())
                .ToArray();
            var utf8Json = JsonSerializer.SerializeToUtf8Bytes(domains, new JsonSerializerOptions { WriteIndented = true });
            File.WriteAllBytes(DOMAINS_JSON_FILE, utf8Json);
        }
        /// 
        /// 获取测试后排序的IP
        /// 
        /// 
        /// 
        public IPAddress[] GetIPAddresses(string domain)
        {
            lock (this.syncRoot)
            {
                if (this.domainIPAddressHashSet.TryGetValue(domain, out var hashSet) && hashSet.Count > 0)
                {
                    return hashSet.ToArray().OrderBy(item => item.PingElapsed).Select(item => item.Address).ToArray();
                }
                return Array.Empty();
            }
        }
        /// 
        /// 进行一轮IP测速
        /// 
        /// 
        /// 
        public async Task TestSpeedAsync(CancellationToken cancellationToken)
        {
            KeyValuePair[] keyValues;
            lock (this.syncRoot)
            {
                keyValues = this.domainIPAddressHashSet.ToArray();
            }
            foreach (var keyValue in keyValues)
            {
                var domain = keyValue.Key;
                var hashSet = keyValue.Value;
                await foreach (var address in this.dnsClient.ResolveAsync(domain, cancellationToken))
                {
                    hashSet.Add(new IPAddressItem(address));
                }
                await hashSet.PingAllAsync();
            }
        }
    }
}