// Copyright © Selmo Technology GmbH. All Rights Reserved

using Microsoft.AspNetCore.Components;
using Novus.Connectivity.Common;
using Novus.Connectivity.Service;
using SelmoStudio.Hmi.Server.Alarms.Service;
using SelmoStudio.Hmi.Server.ProcessValue.Services;
using SelmoStudio.Hmi.Server.SelmoHmi.Cmz.Model.Dtos;
using SelmoStudio.Hmi.Server.SelmoHmi.Cmz.Model.Ids;
using SelmoStudio.Hmi.Server.SelmoHmi.Cmz.Model.Mapper;
using SelmoStudio.Hmi.Server.SelmoHmi.Shared.Service;
using SelmoStudio.Hmi.Server.Shared.Service;
using System.Collections.Immutable;

namespace SelmoStudio.Hmi.Server.SelmoHmi.Cmz.Components
{
    public partial class CmzComponent : LayoutComponentBase, IAsyncDisposable
    {
        [Inject]
        private IProcessValueInfoService _processValueInfoService { get; set; }

        [Inject]
        private IProjectService _projectService { get; set; }

        [Inject]
        private IAlarmService _alarmService { get; set; }

        [Inject]
        private IHmiWatchdog _hmiWatchDog { get; set; }

        [Inject]
        private IProcessValuePollingService _valuePollingService { get; set; }

        private Dictionary<CmzId, CmzDto> _allProjectCmz = new();

        private Dictionary<CmzId, ProcessValueId> _lookupTable = new();

        protected override async Task OnInitializedAsync()
        {
            await base.OnInitializedAsync();
        }

        protected override async Task OnAfterRenderAsync(bool firstRender)
        {
            if (firstRender)
            {
                _allProjectCmz = _projectService.GetAllCmzs().ToDictionary(item => item.Id);
                _hmiWatchDog.OnCycleSecondElapsed += IntervalElapsed;
                var reg = _processValueInfoService.CreateCmzRegistration(_projectService.GetProject());
                _regId = reg.Id;
                _valuePollingService.RegisterValues(reg);
                _lookupTable = _processValueInfoService.CreateCmzLookUpTable(_projectService.GetProject());
            }

            await base.OnAfterRenderAsync(firstRender);
        }

        private ValuesConnectionRegistrationId _regId;

        private void IntervalElapsed(object? sender, WatchdogEventArgs e)
        {
            Task.Run(async () =>
            {
                var valueOperation = await _valuePollingService.GetValues(_regId);

                if (valueOperation.Issues.Any())
                {
                    return;
                }

                var processValues = valueOperation.Value.ProcessValues;

                await Update(processValues);
            });
        }

        private async Task Update(ImmutableDictionary<ProcessValueId, IProcessValue> processValues)
        {
            foreach (var item in _lookupTable)
            {
                var pvId = item.Value;
                var cmzId = item.Key;

                if (!processValues.ContainsKey(pvId) || !_allProjectCmz.ContainsKey(cmzId))
                {
                    continue;
                }

                var isActive = (bool)processValues[pvId].Value;
                if (!isActive)
                {
                    _alarmService.Remove(cmzId.Guid);
                    continue;
                }

                var activeAlarms = await _alarmService.GetActive();
                var cmz = _allProjectCmz[cmzId];
                if (activeAlarms.FirstOrDefault(a => a.Id == cmz.Id.Guid) == null)
                {
                    _alarmService.Add(new()
                    {
                        Id = cmz.Id.Guid,
                        Created = DateTimeOffset.Now,
                        Message = $"Cmz: {cmz.Name} triggered",
                        Severity = CmzTypeToAlarmSeverityMapper.Map(cmz.CmzType),
                        Title = cmz.Name
                    });
                }
            }
        }

        public async ValueTask DisposeAsync()
        {
        }
    }
}