namespace MinicsConsole;

class HostLifetime(
        HardwareFileLoader hardwareFileLoader,
        HardwareDBLoader hardwareDBLoader,
        ConfigFileLoader configFileLoader,
        AddressFileLoader addressFileLoader,
        HardWareMonitor hardWareMonitor,
        ConfigUpdater configUpdater,
        BasicInfo basicInfo,
        OrmCollections ormCollections,
        DataBaseCleaner dataBaseCleaner,
        RTNotifier rtNotifer,
        PLCNotifier plcNotifier,
        DailyRoutinHelper dailyRoutinHelper,
        ITlvProvider tlvProvider,
        ILog log) : IHostedService
{
    //Do all Module Initializations here
    async Task IHostedService.StartAsync(CancellationToken cancellationToken)
    {
        log.Initialize("General");
        //Connect to DataBase Server
        ormCollections.MainORM = new SqlSugarCustom();
        if (string.IsNullOrEmpty(basicInfo.DBConnectionString) ||
            !ormCollections.MainORM.Initialize() ||
            !ormCollections.MainORM.Open(basicInfo.DBConnectionString, DbType.PostgreSQL))
        {
            log.Fatal($"Connect DB Failed");
            Environment.Exit(0);
        }

        if (!hardwareDBLoader.Load())
        {
            hardwareFileLoader.Load();
            hardwareDBLoader.Save();
        }
        configFileLoader.Load();
        addressFileLoader.Load();
        addressFileLoader.LoadPLC();

        //Perparing for data receiver
        if (!plcNotifier.StartService())
        {
            log.Fatal($"PLC configFile Not Exist");
            Environment.Exit(0);
        }
        //Start RT Server
        if (string.IsNullOrEmpty(basicInfo.RTServerAddress) ||
            !rtNotifer.Initialize(tlvProvider) ||
            !rtNotifer.Open(basicInfo.RTServerAddress, basicInfo.RTServerPort))
        {
            log.Fatal($"Open RT Server {basicInfo.RTServerAddress}:{basicInfo.RTServerPort} Failed");
            Environment.Exit(0);
        }

        log.Info($"Start RT Server  {basicInfo.RTServerAddress}:{basicInfo.RTServerPort} success");

        //Connect to Mini8s
        if (!hardWareMonitor.ParallelCreateConnections())
            log.Warning($"Mini8 Addresses error Unable to connect to mini8s");

        //Read Realtime data from mini8 & Read ChannelMode from hareware configruation
        if (configUpdater.ReadConfigFromMini8(out TemperatureConfig? temperatureConfig) && temperatureConfig is not null)
            configUpdater.SetConfigFile(temperatureConfig, false, out _);

        //Start Collecting Mini8s Realtime Data
        hardWareMonitor.ParallelStartDataCollecion();

        dailyRoutinHelper.AddorUpdateRoutinWork("CleanDataBase", dataBaseCleaner.CleanDB);
        dailyRoutinHelper.AddorUpdateRoutinWork("CleanLogFile", ((LogSender)log).CleanLog);
        dailyRoutinHelper.StartService(TimeSpan.FromDays(1));

        await Task.CompletedTask;
    }

    private readonly AutoResetEvent _AutoResetEvent = new(true);
    async Task IHostedService.StopAsync(CancellationToken cancellationToken)
    {
        if (!_AutoResetEvent.WaitOne(0))
            await Task.CompletedTask;

        log.Info("Minics Console has been shutted down by UI request");
        //log.Info("Saving setting files..");
        //hardwareFileLoader.Save();
        //configFileLoader.Save();
        //addressFileLoader.Save();
        //BaseConfigFileLoader.Save(basicInfo);
        log.Info("Closing all mini8 connections..");
        hardWareMonitor.CloseConnections();
        log.Info("Closing RT server connections..");
        rtNotifer?.Dispose();
        log.Info("Closing PLC connections..");
        plcNotifier?.Dispose();
        log.Info("Closing Database connections..");
        ormCollections?.MainORM?.Dispose();
        dailyRoutinHelper?.Dispose();
        log.Info("Finish Stopping..");
        log.Dispose();
        await Task.CompletedTask;
    }
}