using MainShell.Log;
using MwFramework.AlarmManager;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Windows;

namespace MainShell.Alarm
{
    public class AlarmOperate : IAlarmSend, IAlarmResponse<string>
    {
        private const string AlarmSourceName = "AlarmOperate";

        private readonly IAlarmManager _alarmManager;

        public AlarmOperate(IAlarmManager alarmManager)
        {
            _alarmManager = alarmManager ?? throw new ArgumentNullException(nameof(alarmManager));
            _alarmManager.CloseBuzzer += () =>
            {
                LogManager.LogAlarmEvent(AlarmSourceName, "CloseBuzzer");
            };
            _alarmManager.RestBuzzer += () =>
            {
               
            };
            _alarmManager.ClearPLCAlarm += () =>
             {
                 List<long> unresolvedAlarmIds = _alarmManager.UnresolvedAlarms == null
                   ? new List<long>()
                   : _alarmManager.UnresolvedAlarms.Distinct().ToList();

                 try
                 {

                     foreach (long alarmId in unresolvedAlarmIds)
                     {
                         _alarmManager.HandleAlarmSolved(alarmId);
                     }

                     LogManager.LogAlarmEvent(
                         AlarmSourceName,
                         string.Format("ClearPLCAlarm resolved {0} alarms", unresolvedAlarmIds.Count));
                 }
                 catch (Exception ex)
                 {
                     LogManager.LogAlarmError(AlarmSourceName, "ClearPLCAlarm", ex);
                     throw;
                 }
             };
        }

        public string Code { private get; set; }

        public void Alert(int alarmID)
        {
            Task alertTask = AlertAsync(alarmID);

            if (Application.Current != null &&
                Application.Current.Dispatcher != null &&
                Application.Current.Dispatcher.CheckAccess())
            {
                alertTask.ContinueWith(task =>
                {
                    AggregateException ignored = task.Exception;
                }, TaskContinuationOptions.OnlyOnFaulted);
                return;
            }

            alertTask.GetAwaiter().GetResult();
        }

        public void Alert(int alarmID, string source, string action, string detail = null)
        {
            Task alertTask = AlertAsync(alarmID, source, action, detail);

            if (Application.Current != null &&
                Application.Current.Dispatcher != null &&
                Application.Current.Dispatcher.CheckAccess())
            {
                alertTask.ContinueWith(task =>
                {
                    AggregateException ignored = task.Exception;
                }, TaskContinuationOptions.OnlyOnFaulted);
                return;
            }

            alertTask.GetAwaiter().GetResult();
        }
        
        public async Task AlertAsync(int alarmID)
        {
            await AlertInternalAsync(alarmID, AlarmSourceName, "AlertAsync requested").ConfigureAwait(false);
        }

        public async Task AlertAsync(int alarmID, string source, string action, string detail = null)
        {
            string alarmSource = string.IsNullOrWhiteSpace(source) ? AlarmSourceName : source;
            string triggerAction = BuildTriggerAction(action, detail);

            await AlertInternalAsync(alarmID, alarmSource, triggerAction).ConfigureAwait(false);
        }

        private async Task AlertInternalAsync(int alarmID, string source, string action)
        {
            try
            {
                LogManager.LogAlarmEvent(source, action, alarmID);
                await _alarmManager.HandleAlarmAsync(alarmID, this, this).ConfigureAwait(false);
                LogManager.LogAlarmEvent(source, "HandleAlarmAsync completed", alarmID);
            }
            catch (Exception ex)
            {
                LogManager.LogAlarmError(source, "HandleAlarmAsync", ex, alarmID);
                throw;
            }
        }

        private static string BuildTriggerAction(string action, string detail)
        {
            string normalizedAction = string.IsNullOrWhiteSpace(action) ? "AlertAsync requested" : action;

            if (string.IsNullOrWhiteSpace(detail))
            {
                return normalizedAction;
            }

            return string.Format("{0}. Detail={1}", normalizedAction, detail);
        }
    }
}
