using Microsoft.Extensions.Options;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Net;
namespace FastGithub
{
    /// 
    /// FastGithub配置
    /// 
    public class FastGithubConfig
    {
        /// 
        /// 域名与配置缓存
        /// 
        [AllowNull]
        private ConcurrentDictionary domainConfigCache;
        /// 
        /// 未污染的dns
        /// 
        [AllowNull]
        public IPEndPoint PureDns { get; private set; }
        /// 
        /// 速度快的dns
        /// 
        [AllowNull]
        public IPEndPoint FastDns { get; private set; }
        /// 
        /// 获取域名配置
        /// 
        [AllowNull]
        public Dictionary DomainConfigs { get; private set; }
        /// 
        /// FastGithub配置
        ///  
        /// 
        public FastGithubConfig(IOptionsMonitor options)
        {
            this.Init(options.CurrentValue);
            options.OnChange(opt => this.Init(opt));
        }
        /// 
        /// 初始化
        /// 
        /// 
        private void Init(FastGithubOptions options)
        {
            this.domainConfigCache = new ConcurrentDictionary();
            this.PureDns = options.PureDns.ToIPEndPoint();
            this.FastDns = options.FastDns.ToIPEndPoint();
            this.DomainConfigs = options.DomainConfigs.ToDictionary(kv => new DomainMatch(kv.Key), kv => kv.Value);
        }
        /// 
        /// 是否匹配指定的域名
        /// 
        /// 
        /// 
        public bool IsMatch(string domain)
        {
            return this.DomainConfigs.Keys.Any(item => item.IsMatch(domain));
        }
        /// 
        /// 尝试获取域名配置
        /// 
        /// 
        /// 
        /// 
        public bool TryGetDomainConfig(string domain, [MaybeNullWhen(false)] out DomainConfig value)
        {
            value = this.domainConfigCache.GetOrAdd(domain, GetDomainConfig);
            return value != null;
            DomainConfig? GetDomainConfig(string domain)
            {
                var key = this.DomainConfigs.Keys.FirstOrDefault(item => item.IsMatch(domain));
                return key == null ? null : this.DomainConfigs[key];
            }
        }
    }
}