// Copyright © Selmo Technology GmbH. All Rights Reserved

using Microsoft.AspNetCore.Components;
using Novus.Connectivity.Service;
using SelmoStudio.Hmi.Server.Alarms.Model;
using SelmoStudio.Hmi.Server.Alarms.Service;
using SelmoStudio.Hmi.Server.ProcessValue.Services;
using SelmoStudio.Hmi.Server.SelmoHmi.Authentication.Service;
using SelmoStudio.Hmi.Server.SelmoHmi.Connection.Service;
using SelmoStudio.Hmi.Server.SelmoHmi.Dialog.Service;
using SelmoStudio.Hmi.Server.SelmoHmi.Issues.Components;
using SelmoStudio.Hmi.Server.SelmoHmi.Shared.Service;
using SelmoStudio.Hmi.Server.Shared.Resources;
using SelmoStudio.Hmi.Server.Shared.Service;
using SelmoStudio.Hmi.Server.TestSetup;

namespace SelmoStudio.Hmi.Server.Shared.Pages
{
    public partial class MainLayout : LayoutComponentBase, IDisposable
    {
        private ValuesConnectionRegistration _registration;
        private int intervallElapsedCounter;
        private TestIssuesBuilder _testIssuesBuilder;
        private bool _testIssueReportDialog = false;

        private IHmiDialogService _issueReportDialogService;

        private bool _notifyLostConnection;

        private event Action OnConnectionLost;

        private Alarm _connectionLostAlarm;

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

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

        [Inject]
        private IOperationResultIssuesService _operationResultIssuesService { get; set; }

        [Inject]
        private IAuthenticationStateService _authenticationStateService { get; set; }

        [Inject]
        private NavigationManager _navigationManager { get; set; }

        [Inject]
        private IConnectionService _connectionService { get; set; }

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

        protected override void OnInitialized()
        {
            _hmiWatchDog.OnCycleSecondElapsed += IntervalElapsed;

            _authenticationStateService.AuthenticationStateChanged += OnAuthenticationStateChangedAsync;

            _notifyLostConnection = true;
            OnConnectionLost += _connectionService.Connect;
            _connectionService.OnConnectionEstablished += async () => await OnConnectionEstablished();
            _connectionLostAlarm = new Alarm
            {
                Id = Guid.Parse("ea26fb07-2f93-462a-8ede-fdbce8f3fc54"),
                AlarmType = Alarms.Model.Dto.AlarmType.Standard,
                Severity = Severity.Fatal,
                Title = $"{HmiResource.ServerConnection}",
                Message = $"{HmiResource.ServerConnection}: {HmiResource.Disconnected}",
                NavigateUrl = "selmoDiagnose"
            };

            base.OnInitialized();
        }

        private void IntervalElapsed(object sender, WatchdogEventArgs e)
        {
            if (!_processValuePollingService.IsConnectionActive() && _notifyLostConnection)
            {
                HandleLostConnection();
            }

            if (_processValuePollingService.IsConnectionActive() && !_notifyLostConnection)
            {
                HandleAutomaticallyEstablishedConnection();
            }
        }

        private void HandleLostConnection()
        {
            _notifyLostConnection = false;
            _connectionLostAlarm.Created = DateTimeOffset.Now;
            _alarmService.Add(_connectionLostAlarm);
            OnConnectionLost?.Invoke();
        }

        private void HandleAutomaticallyEstablishedConnection()
        {
            OnConnectionLost?.Invoke();
        }

        private async Task OnConnectionEstablished()
        {
            _notifyLostConnection = true;
            _alarmService.Remove(_connectionLostAlarm.Id);

            await InvokeAsync(() => StateHasChanged());

            _navigationManager.NavigateTo(_navigationManager.Uri, forceLoad: true);
        }

        private void IssuesProcessed(object? sender, ProcessedIssuesArgs args)
        {
            Task.Run(async () =>
            {
                var parameters = new Dictionary<string, object>() { { "Issues", args.Issues }, { "UnknownIssueOccured", args.UnknownIssueOccured },
                { "UseConditionalFormatting", true }, { "DiagnoseUrl", "selmoDiagnose" } };

                await InvokeAsync(() => _issueReportDialogService.OpenDialogAsync<IssueReportDialogComponent>(@_localizer[nameof(HmiResource.IssuesReport)],
                    "90%", "55vh", parameters));
            });
        }

        private async Task OnAuthenticationStateChangedAsync()
        {
            await InvokeAsync(() => StateHasChanged());

            _navigationManager.NavigateTo(_navigationManager.Uri, forceLoad: true);
        }

        public void Dispose()
        {
            _hmiWatchDog.OnCycleSecondElapsed -= IntervalElapsed;
            _operationResultIssuesService.OnIssuesProcessed -= IssuesProcessed;

            if (_issueReportDialogService != null)
            {
                ((HmiDialogService)_issueReportDialogService).Dispose();
            }

            if (_connectionService != null)
            {
                OnConnectionLost -= _connectionService.Connect;
                _connectionService.OnConnectionEstablished -= async () => await OnConnectionEstablished();
            }

            _authenticationStateService.AuthenticationStateChanged -= OnAuthenticationStateChangedAsync;
        }
    }
}