using FastGithub.Scanner.ScanMiddlewares;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using System;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
namespace FastGithub.Scanner
{
    /// 
    /// github扫描服务
    /// 
    [Service(ServiceLifetime.Singleton)]
    sealed class GithubScanService
    {
        private readonly GithubLookupFacotry lookupFactory;
        private readonly GithubContextCollection scanResults;
        private readonly ILogger logger;
        private readonly InvokeDelegate fullScanDelegate;
        private readonly InvokeDelegate resultScanDelegate;
        /// 
        /// github扫描服务
        /// 
        /// 
        /// 
        /// 
        /// 
        public GithubScanService(
            GithubLookupFacotry lookupFactory,
            GithubContextCollection scanResults,
            IServiceProvider appService,
            ILogger logger)
        {
            this.lookupFactory = lookupFactory;
            this.scanResults = scanResults;
            this.logger = logger;
            this.fullScanDelegate = new PipelineBuilder(appService, ctx => Task.CompletedTask)
                .Use()
                .Use()
                .Use()
                .Use()
                .Build();
            this.resultScanDelegate = new PipelineBuilder(appService, ctx => Task.CompletedTask)
                .Use()
                .Use()
                .Build();
        }
        /// 
        /// 扫描所有的ip
        /// 
        /// 
        public async Task ScanAllAsync(CancellationToken cancellationToken)
        {
            this.logger.LogInformation("完整扫描开始..");
            var domainAddresses = await this.lookupFactory.LookupAsync(cancellationToken);
            var scanTasks = domainAddresses
                .Select(item => new GithubContext(item.Domain, item.Address, cancellationToken))
                .Select(ctx => ScanAsync(ctx));
            var results = await Task.WhenAll(scanTasks);
            var successCount = results.Count(item => item);
            this.logger.LogInformation($"完整扫描结束,成功{successCount}条共{results.Length}条");
            async Task ScanAsync(GithubContext context)
            {
                await this.fullScanDelegate(context);
                if (context.Available == true)
                {
                    this.scanResults.Add(context);
                }
                return context.Available;
            }
        }
        /// 
        /// 扫描曾经扫描到的结果
        /// 
        /// 
        public async Task ScanResultAsync()
        {
            this.logger.LogInformation("结果扫描开始..");
            var results = this.scanResults.ToArray();
            var contexts = results
                .OrderBy(item => item.Domain)
                .ThenByDescending(item => item.History.AvailableRate)
                .ThenBy(item => item.History.AvgElapsed);
            foreach (var context in contexts)
            {
                await this.resultScanDelegate(context);
            }
            this.logger.LogInformation($"结果扫描结束,共扫描{results.Length}条记录");
        }
    }
}