using System;
using System.Threading;
using System.Threading.Tasks;
using System.Diagnostics;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Hosting;
using AsbCloudInfrastructure.Services.Cache;
using AsbCloudApp.Services;
using AsbCloudDb.Model;
using Microsoft.Extensions.Configuration;

namespace AsbCloudInfrastructure.Services.Analysis
{
    public class TelemetryAnalyticsBackgroundService : BackgroundService
    {
        private readonly CacheDb cacheDb;
        private readonly ITelemetryTracker telemetryTracker;
        private readonly string connectionString;
        private readonly TimeSpan period = TimeSpan.FromHours(1);

        public TelemetryAnalyticsBackgroundService(CacheDb cacheDb, ITelemetryTracker telemetryTracker, IConfiguration configuration)
        {
            this.cacheDb = cacheDb;
            this.telemetryTracker = telemetryTracker;
            connectionString = configuration.GetConnectionString("DefaultConnection");
        }

        protected override async Task ExecuteAsync(CancellationToken token = default)
        {
            var timeToStartAnalysis = DateTime.Now;
            var options = new DbContextOptionsBuilder<AsbCloudDbContext>()
                .UseNpgsql(connectionString)
                .Options;

            while (!token.IsCancellationRequested)
            {
                if(DateTime.Now > timeToStartAnalysis)
                {
                    timeToStartAnalysis = DateTime.Now + period;
                    try
                    {
                        using var context = new AsbCloudDbContext(options);
                        var timeZoneService = new TimeZoneService();
                        var telemetryService = new TelemetryService(context, telemetryTracker, timeZoneService, cacheDb);
                        var analyticsService = new TelemetryAnalyticsService(context,
                            telemetryService, cacheDb);

                        await analyticsService.AnalyzeAndSaveTelemetriesAsync(token).ConfigureAwait(false);
                        context.ChangeTracker.Clear();
                        context.Dispose();
                    }
                    catch (Exception ex)
                    {
                        Trace.TraceError(ex.Message);
                        Console.WriteLine(ex.Message);
                    }
                    GC.Collect();
                }

                var ms = (int)(timeToStartAnalysis - DateTime.Now).TotalMilliseconds;
                ms = ms > 100 ? ms : 100;
                await Task.Delay(ms, token).ConfigureAwait(false);                
            }
        }

        public override async Task StopAsync(CancellationToken token)
        {
            await base.StopAsync(token).ConfigureAwait(false);
        }

    }
}