using LogoForceTestApp.Modules.MainModule.Models;
using Microsoft.Extensions.Options;
using Prism.Events;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Data;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Team.Utility;

namespace LogoForceTestApp.Modules.MainModule.Services
{
    public class WarningUpdateService : IWarningUpdateService
    {
        private readonly IEventAggregator _eventAggregator;
        private readonly IOptions<AppSettings> _appSettings;
        private readonly ConcurrentDictionary<int, DeviceErrorLog> _deviceErrorLogs = new();
        private readonly ushort[] _tempData;
        private readonly ConcurrentDictionary<int, Tuple<int,string>> _warningList = new();
        public WarningUpdateService(IEventAggregator eventAggregator, IOptions<AppSettings> appSettings)
        {
            _tempData = new ushort[100];
            _eventAggregator = eventAggregator;
            _appSettings = appSettings;
            var filePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "ErrorCode.xlsx");
            if (File.Exists(filePath))
            {
                var dataTable = ExcelUtil.ExcelToTable(filePath);
                foreach (DataRow row in dataTable.Rows)
                {
                    int id = int.Parse(row[0].ToString());
                    int errorCode = int.Parse(row[1].ToString());

                    _warningList.TryAdd(id, new Tuple<int,string>(errorCode, row[2].ToString()));
                }
            }
            else
            {
                var dataTable = new DataTable();
                dataTable.Columns.Add("报警编号");
                dataTable.Columns.Add("报警代码");
                dataTable.Columns.Add("报警信息");
                for (int i = 1; i <= 16 * 100; i++)
                {
                    dataTable.Rows.Add(i.ToString(), 60020000 + i,$"未定义错误{i}");
                }

                foreach (DataRow row in dataTable.Rows)
                {
                    int id = int.Parse(row[0].ToString());
                    int errorCode = int.Parse(row[1].ToString());
                    _warningList.TryAdd(id, new Tuple<int, string>(errorCode, row[2].ToString()));
                }
                ExcelUtil.TableToExcel(dataTable, filePath, true);
            }

        }

        public Tuple<int,string> GetErrorCode(int id)
        {
            if (!_warningList.ContainsKey(id))
            {
                return Tuple.Create(1, "error");
            }
            return _warningList[id];
        }
        public async Task  UpdateWarningAsync(ushort[] data)
        {
            if (data is null)
            {
                throw new ArgumentNullException(nameof(data));
            }

            if (data.Length < 100)
            {
                throw new ArgumentException(nameof(data) + "长度不正确,长度数据应为100");
            }



            //var content = "X2,2022/9/2,D,TEAM,HSG,L1,M-04Fasten SANP to HSG(2x screws),001,H18-001,后门禁报警,9:51:05,9:58:04,419";
            for (int i = 0; i < 100; i++)
            {
                if (_tempData[i] != data[i])
                {
                    var tempSingleValue = _tempData[i];
                    var currentSingleValue = data[i];
                    var tempArray = IntTo16BoolArray(tempSingleValue);
                    var currentArray = IntTo16BoolArray(currentSingleValue);
                    for (int j = 0; j < 16; j++)
                    {
                        var id = j + 1 + i * 16;
                        if (!tempArray[j] && currentArray[j])
                        {
                            //error occured

                            if (!_deviceErrorLogs.ContainsKey(id))
                            {
                                //_deviceErrorLogs.TryAdd(id, new DeviceErrorLog
                                //{
                                //    Category = "X2",
                                //    Class = "D",
                                //    Vendor = _deviceParam.Vendor,
                                //    Date = DateTime.Today.ToString("yyyy-MM-dd"),
                                //    SegmentName = _deviceParam.SegmentName,
                                //    LineId = _deviceParam.LineName,
                                //    DeviceId = _deviceParam.DeviceId,
                                //    Jig = "H18-001",
                                //    StartTime = DateTime.Now,
                                //    WaringInfo = _warningList[id],
                                //    WorkStaionName = _deviceParam.WorkStaionName,

                                //});
                                _eventAggregator.GetEvent<WaringUpdateLog>().Publish(new Tuple<LogType, string>(LogType.Error, $"信号{id}" + _warningList[id]));
                            }
                        }
                        else if (tempArray[j] && !currentArray[j])
                        {
                            if (_deviceErrorLogs.ContainsKey(id))
                            {
                                try
                                {
                                    _deviceErrorLogs.TryRemove(id, out var deviceErrorLog);
                                    deviceErrorLog.EndTime = DateTime.Now;
                                    var start = deviceErrorLog.StartTime;
                                    var end = deviceErrorLog.EndTime;
                                    deviceErrorLog.Duration = (end - start).TotalSeconds;
                                    await WriteLogAsync(deviceErrorLog);
                                    _eventAggregator.GetEvent<WaringUpdateLog>().Publish(new Tuple<LogType, string>(LogType.Info, _warningList[id] + $"已经处理完毕,持续时间:{deviceErrorLog.Duration}s"));
                                }
                                catch (Exception)
                                {
                                }

                            }

                        }
                    }
                    _tempData[i] = data[i];
                }
            }
        }
        async Task WriteLogAsync(DeviceErrorLog deviceErrorLog)
        {
            //if (string.IsNullOrWhiteSpace(_deviceParam.WarningReocordPath))
            //{
            //    _deviceParam.WarningReocordPath = "d:/Files";
            //}
            //var directoryName = _deviceParam.WarningReocordPath;
            //if (!Directory.Exists(directoryName))
            //{
            //    Directory.CreateDirectory(directoryName);
            //    Thread.Sleep(1);
            //}
            //var fileName = DateTime.Today.ToString("yyy_MM_dd") + "_报警日志" + ".csv";
            //var filePath = Path.Combine(directoryName, fileName);
            //bool writeHeader = !File.Exists(filePath);
            //var header = "机种,日期,班别,厂商,段别,线别,工站名称,机台编号,治具编号,报警信息,报警开始时间,报警结束时间,DT(s)";
            //using var streamWriter = new StreamWriter(filePath, true, Encoding.GetEncoding("gb2312"));
            //if (writeHeader)
            //{
            //    await streamWriter.WriteLineAsync(header);
            //}
            //await streamWriter.WriteLineAsync(deviceErrorLog.ToString());
            //await streamWriter.FlushAsync();
            //streamWriter.Close();
        }
        /// <summary>
        /// 整型转16位布尔数组
        /// </summary>
        /// <param name="inputNum"></param>
        /// <returns></returns>
        private bool[] IntTo16BoolArray(ushort inputNum)
        {
            bool[] boolArray = new bool[16];
            for (int i = 0; i < boolArray.Length; i++)
            {
                if (inputNum % 2 == 1)
                    boolArray[i] = true;
                else
                    boolArray[i] = false;
                inputNum = (ushort)(inputNum / 2);
            }
            return boolArray;
        }

    }

    public class DeviceErrorLog
    {
        public string Category { get; set; }
        public string Date { get; set; }
        public string Class { get; set; }
        public string Vendor { get; set; }
        public string SegmentName { get; set; }
        public string LineId { get; set; }
        public string WorkStaionName { get; set; }
        public string DeviceId { get; set; }
        public string Jig { get; set; }
        public string WaringInfo { get; set; }
        public DateTime StartTime { get; set; }
        public DateTime EndTime { get; set; }
        public double Duration { get; set; }
        public override string ToString()
        {
            return $"{Category},{Date},{Class},{Vendor},{SegmentName},{LineId},{WorkStaionName},{DeviceId},{Jig},{WaringInfo}," +
                $"{StartTime:HH:mm:ss},{EndTime:HH:mm:ss},{Duration}";
        }
    }

}