using FastGithub.Configuration;
using Microsoft.Extensions.Logging;
using System;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Linq;
using System.Net;
using System.Threading.Tasks;
namespace FastGithub.Dns
{
    /// 
    /// host文件配置验证器
    /// 
    sealed class HostsValidator : IDnsValidator
    {
        private readonly FastGithubConfig fastGithubConfig;
        private readonly ILogger logger;
        /// 
        /// host文件配置验证器
        /// 
        /// 
        /// 
        public HostsValidator(
            FastGithubConfig fastGithubConfig,
            ILogger logger)
        {
            this.fastGithubConfig = fastGithubConfig;
            this.logger = logger;
        }
        /// 
        /// 验证host文件的域名解析配置 
        /// 
        /// 
        public async Task ValidateAsync()
        {
            var hostsPath = @"/etc/hosts";
            if (OperatingSystem.IsWindows())
            {
                hostsPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.System), $"drivers/{hostsPath}");
            }
            if (File.Exists(hostsPath) == false)
            {
                return;
            }
            var localAddresses = LocalMachine.GetAllIPv4Addresses().ToArray();
            var lines = await File.ReadAllLinesAsync(hostsPath);
            foreach (var line in lines)
            {
                if (HostsRecord.TryParse(line, out var record) == false)
                {
                    continue;
                }
                if (localAddresses.Contains(record.Address) == true)
                {
                    continue;
                }
                if (this.fastGithubConfig.IsMatch(record.Domain))
                {
                    this.logger.LogError($"由于你的hosts文件设置了{record},{nameof(FastGithub)}无法加速此域名");
                }
            }
        }
        /// 
        /// hosts文件记录
        /// 
        private class HostsRecord
        {
            /// 
            /// 获取域名
            /// 
            public string Domain { get; }
            /// 
            /// 获取地址
            /// 
            public IPAddress Address { get; }
            private HostsRecord(string domain, IPAddress address)
            {
                this.Domain = domain;
                this.Address = address;
            }
            public override string ToString()
            {
                return $"[{this.Domain}->{this.Address}]";
            }
            public static bool TryParse(string record, [MaybeNullWhen(false)] out HostsRecord value)
            {
                value = null;
                if (record.TrimStart().StartsWith("#"))
                {
                    return false;
                }
                var items = record.Split(' ', StringSplitOptions.RemoveEmptyEntries);
                if (items.Length < 2)
                {
                    return false;
                }
                if (IPAddress.TryParse(items[0], out var address) == false)
                {
                    return false;
                }
                value = new HostsRecord(items[1], address);
                return true;
            }
        }
    }
}