using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Threading;
namespace FastGithub.Scanner
{
    /// 
    /// Github扫描上下文
    /// 
    sealed class GithubContext : DomainAddress, IEquatable
    {
        /// 
        /// 最多保存最的近的10条记录
        /// 
        private const int MAX_LOG_COUNT = 10;
        /// 
        /// 扫描记录
        /// 
        private record ScanLog(bool Available, TimeSpan Elapsed);
        /// 
        /// 扫描历史记录
        /// 
        private readonly Queue history = new();
        /// 
        /// 设置取消令牌
        /// 
        public CancellationToken CancellationToken { get; }
        /// 
        /// 获取可用率
        /// 
        /// 
        public double AvailableRate => this.GetAvailableRate();
        /// 
        /// 获取平均耗时
        /// 
        /// 
        public TimeSpan AvgElapsed => this.GetAvgElapsed();
        /// 
        /// 获取或设置是否可用
        /// 
        public bool Available { get; set; }
        /// 
        /// Github扫描上下文
        /// 
        /// 
        /// 
        public GithubContext(string domain, IPAddress address)
            : this(domain, address, CancellationToken.None)
        {
        }
        /// 
        /// Github扫描上下文
        /// 
        /// 
        /// 
        /// 
        public GithubContext(string domain, IPAddress address, CancellationToken cancellationToken)
            : base(domain, address)
        {
            this.CancellationToken = cancellationToken;
        }
        /// 
        /// 获取可用率
        /// 
        /// 
        private double GetAvailableRate()
        {
            if (this.history.Count == 0)
            {
                return 0d;
            }
            var availableCount = this.history.Count(item => item.Available);
            return (double)availableCount / this.history.Count;
        }
        /// 
        /// 获取平均耗时
        /// 
        /// 
        private TimeSpan GetAvgElapsed()
        {
            var availableCount = 0;
            var availableElapsed = TimeSpan.Zero;
            foreach (var item in this.history)
            {
                if (item.Available == true)
                {
                    availableCount += 1;
                    availableElapsed = availableElapsed.Add(item.Elapsed);
                }
            }
            return availableCount == 0 ? TimeSpan.MaxValue : availableElapsed / availableCount;
        }
        /// 
        /// 添加扫描记录
        /// 
        /// 扫描耗时
        public void AddScanLog(TimeSpan elapsed)
        {
            var log = new ScanLog(this.Available, elapsed);
            this.history.Enqueue(log);
            while (this.history.Count > MAX_LOG_COUNT)
            {
                this.history.Dequeue();
            }
        }
        /// 
        /// 是否相等
        /// 
        /// 
        /// 
        public bool Equals(GithubContext? other)
        {
            return base.Equals(other);
        }
        /// 
        /// 转换为统计信息
        /// 
        /// 
        public string ToStatisticsString()
        {
            var availableRate = Math.Round(this.AvailableRate * 100, 2);
            return $"{{{nameof(Address)}={this.Address}, {nameof(AvailableRate)}={availableRate}%, {nameof(AvgElapsed)}={this.AvgElapsed.TotalSeconds}s}}";
        }
    }
}