using AlarmMonitorWorkerService.Models;
using Microsoft.Extensions.Logging;
using Quartz;
using Repository.FrontendRepository.Interface;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Windows.Data.Xml.Dom;
using Windows.UI.Notifications;
using System.IO;

namespace AlarmMonitorWorkerService.Quartz.Jobs
{
    /// <summary>
    /// 監控緊急應變畫面是否有開啟
    /// </summary>
    [DisallowConcurrentExecution]
    class AlarmMonitorJob : IJob
    {
        private const string APP_ID = "WPF ToastNotificaiton Test";
        private readonly ILogger<AlarmMonitorJob> logger;
        private readonly IFrontendRepository frontendRepository;

        public AlarmMonitorJob(
           ILogger<AlarmMonitorJob> logger,
           IFrontendRepository frontendRepository)
        {
            this.logger = logger;
            this.frontendRepository = frontendRepository;
        }

        public async Task Execute(IJobExecutionContext context)
        {
            try
            {
                logger.LogInformation("【AlarmMonitorJob】【任務開始】");
                //找出當前緊急應變的PID
                var sqlWatchDog = $@"SELECT system_value as Value, system_key as Name FROM variable WHERE deleted = 0 AND system_type = 'watchDogCongfig'";

                var variable = await frontendRepository.GetAllAsync<KeyValue>(sqlWatchDog);
                var alarmPID = variable.Where(x => x.Name == "AlarmPID").Select(x => x.Value).FirstOrDefault();

                var category = new PerformanceCounterCategory("Process");

                var instances = category.GetInstanceNames();

                var hasFound = false;
                foreach (var instance in instances)
                {
                    try
                    {
                        using (var counter = new PerformanceCounter(category.CategoryName,
                                                 "ID Process", instance, true))
                        {
                            int val = (int)counter.RawValue;
                            if (val == Convert.ToInt32(alarmPID))
                            {
                                hasFound = true;
                                break;
                            }
                        }
                    }
                    catch (Exception exception)
                    {

                    }
                }

                var header = string.Empty;
                if (!hasFound)
                {
                    header = "請開啟監控頁面";
                }

                //找出異常的設備
                string sql = $@"SELECT 
                                    amc.id,
                                    sl.source source_path,
                                    from_unixtime(amc.timestamp/1000,'%Y-%m-%d %H:%i:%s') alarm_timestamp ,
                                    temp_source.source_name,
                                    temp_msg.source_msg
                                FROM alarmorion_orionalarmrecord amc
                                JOIN (
	                                SELECT 
                                        MAX(amc.alarm) ad,
                                        m.source 
                                    FROM alarmorion_orionalarmsourceorder amc
	                                JOIN (
                                        SELECT * FROM alarmorion_orionalarmsource a 
                                        WHERE substring(a.source,23,5) ='Arena'
                                    ) m ON amc.alarmSource = m.id
	                                GROUP BY m.source
                                ) sl ON amc.id = sl.ad
                                JOIN(
                                    SELECT
                                        val.alarm ,
                                        val.value AS source_name
                                    FROM alarmorion_orionalarmfacetvalue val 
                                    JOIN alarmorion_orionalarmfacetname nam ON val.facetName = nam.id AND nam.facetName = 'sourceName'
                                ) temp_source ON amc.id = temp_source.alarm
                                JOIN(
                                    SELECT 
                                        val.alarm,
                                        val.value AS source_msg
                                    FROM alarmorion_orionalarmfacetvalue val 
                                    JOIN alarmorion_orionalarmfacetname nam ON val.facetName = nam.id AND nam.facetName = 'msgText'
                                ) temp_msg ON amc.id = temp_msg.alarm
                                WHERE amc.sourceState = 1";

                var alarms = await frontendRepository.GetAllAsync<AlarmorionString>(sql);

                //組出device_number
                List<string> tempDeviceNumbers = new List<string>();
                foreach (var alarm in alarms)
                {
                    var alarmSplit = alarm.source_path.Split("|");
                    var deviceSplit = alarmSplit[alarmSplit.Length - 1].Split("/");
                    var device_number = deviceSplit[deviceSplit.Length - 3];
                    var point = deviceSplit[deviceSplit.Length - 2];

                    alarm.device_number = device_number.Replace("$3", "");
                    alarm.point = point;

                    tempDeviceNumbers.Add(device_number);
                }

                //找出所有設備相關資訊
                var sql_device = $@"SELECT 
                                        d.device_number,
                                        d.full_name AS device_name,
	                                    b.full_name AS building_name,
	                                    f.full_name AS floor_name,
                                       (SELECT
                                         v.system_key
                                         FROM device_disaster dd 
                                         JOIN variable v ON v.deleted = 0 AND v.system_type = 'disaster' AND v.system_value = dd.device_system_value
                                         WHERE dd.device_guid = d.device_guid
	                                    ) AS Device_disaster_type_text
                                    FROM device d
                                    JOIN building b ON b.deleted = 0 AND d.building_guid = b.building_guid
                                    JOIN floor f ON f.deleted = 0 AND d.floor_guid = f.floor_guid
                                    WHERE d.deleted = 0 AND d.device_number IN @device_numbers";

                var deviceInfos = await frontendRepository.GetAllAsync<DeviceInfo>(sql_device, new { device_numbers = tempDeviceNumbers.Distinct().ToList() });

                var alarmFormat = @"{0}:{1} {2} {3} {4} {5}觸發";

                List<string> alarmMsg = new List<string>();
                foreach (var alarm in alarms)
                {
                    var selected_deviceinfo = deviceInfos.Where(x => x.device_number == alarm.device_number).FirstOrDefault();

                    if (selected_deviceinfo != null)
                    {
                        alarmMsg.Add(string.Format(alarmFormat,
                           selected_deviceinfo.device_disaster_type_text,
                           alarm.alarm_timestamp,
                           selected_deviceinfo.building_name,
                           selected_deviceinfo.floor_name,
                           selected_deviceinfo.device_name,
                           alarm.point));
                    }
                }

                GenerateToast("IBMS緊急應變通知", null, header, "", string.Join("\n", alarmMsg));
                logger.LogInformation("【AlarmMonitorJob】【任務完成】");
            }
            catch (Exception exception)
            {
                logger.LogError("【AlarmMonitorJob】【任務失敗】");
                logger.LogError("【AlarmMonitorJob】【任務失敗】[Exception]:{0}", exception.ToString());
            }
        }

        public void GenerateToast(string appid, string imageFullPath, string h1, string h2, string p1)
        {
            try
            {

                var template = ToastNotificationManager.GetTemplateContent(ToastTemplateType.ToastImageAndText04);

                var textNodes = template.GetElementsByTagName("text");

                textNodes[0].AppendChild(template.CreateTextNode(h1));
                textNodes[1].AppendChild(template.CreateTextNode(h2));
                textNodes[2].AppendChild(template.CreateTextNode(p1));

                //if (File.Exists(imageFullPath))
                //{
                //    XmlNodeList toastImageElements = template.GetElementsByTagName("image");
                //    ((XmlElement)toastImageElements[0]).SetAttribute("src", imageFullPath);
                //}

                IXmlNode toastNode = template.SelectSingleNode("/toast");
                ((XmlElement)toastNode).SetAttribute("duration", "long");

                var notifier = ToastNotificationManager.CreateToastNotifier(appid);
                var notification = new ToastNotification(template);

                notifier.Show(notification);
            }
            catch (Exception)
            {
                // Ignore
            }
        }
    }
}