using AngleSharp.Css.Dom;
using Masuit.Tools;
using PVDEMCS.Common.Constant;
using PVDEMCS.Common.Log;
using PVDEMCS.Devices;
using PVDEMCS.Services;
using PVDEMCS.Services.Impl;
using PVDEMCS.Services.Models;
using System.Linq;
using System.Threading;

namespace PVDEMCS.Devices.Impl
{
    /// <summary>
    /// 设备运行
    /// </summary>
    public class DeviceRun : IDeviceRun
    {
        private IDeviceService deviceService;
        private IEquipmentRecordService equipmentRecordService;
        private List<DeviceMonitor> monitors = new List<DeviceMonitor>();
        private object lockObj = new object();
        private object lockObj1 = new object();

        public DeviceRun(IDeviceService deviceService, IEquipmentRecordService equipmentRecordService)
        {
            this.deviceService = deviceService;
            this.equipmentRecordService = equipmentRecordService;
            TaskRun();
        }

        /// <summary>
        /// 获取所有点位信息
        /// </summary>
        public List<DevicePoint> GetDevicePoints
        {
            get
            {
                return monitors.SelectMany(f => f.Points).ToList();
            }
        }

        /// <summary>
        /// 获取控制器连接状态
        /// </summary>
        public Dictionary<string, bool> GetDeviceIsConnected
        {
            get
            {
                return monitors.ToDictionary(f => f.DeviceCode, f => f.IsConnected);
            }
        }

        /// <summary>
        /// 开始运行
        /// </summary>
        public void Run()
        {
            Stop();

            monitors.Clear();

            var result = deviceService.GetDeviceInfoList("", "", true);
            if (result.IsSuccess)
            {
                var devices = result.Content;
                foreach (var device in devices)
                {
                    var deviceMonitor = new DeviceMonitor(device);
                    var devicePoints = deviceService.GetDevicePointList(device.Id, activated: true);
                    if (devicePoints.IsSuccess && devicePoints.Content.Count > 0)
                    {
                        deviceMonitor.Load(devicePoints.Content.ToArray());
                    }
                    deviceMonitor.ErrorMessage += DeviceMonitor_ErrorMessage;
                    deviceMonitor.PointChange += DeviceMonitor_PointChnage; ;
                    monitors.Add(deviceMonitor);
                    Task<bool> task = deviceMonitor.StartAsync();
                    ($"PLC控制器：{device.DeviceCode}，开始启动...").WriteInfoLog();
                }
            }
        }

        /// <summary>
        /// 停止运行
        /// </summary>
        public void Stop()
        {
            foreach (var item in monitors)
            {
                var task = item.StopAsync();
            }
        }

        //
        private void TaskRun()
        {
            //监控设备连接
            Task.Run(() =>
            {
                while (true)
                {
                    foreach (var item in monitors)
                    {
                        try
                        {
                            var task = item.StartAsync();
                        }
                        catch (Exception ex)
                        {
                            ex.WriteErrorLog("监控设备连接异常");
                        }
                    }

                    Thread.Sleep(5000);
                }
            });

            //添加设备记录
            Task.Run(() =>
            {
                while (true)
                {
                    RunEquipmentRecord();

                    Thread.Sleep(3000);
                }
            });

            //设备记录日统计
            Task.Run(() =>
            {
                while (true)
                {
                    try
                    {
                        equipmentRecordService.RunEquipmentRecordDayTotal(DateTime.Now);
                    }
                    catch (Exception ex)
                    {
                         ex.WriteErrorLog("设备记录日统计异常");
                    }

                    Thread.Sleep(1000 * 60);

                }
            });

            //设备记录统计
            Task.Run(() =>
            {
                while (true)
                {
                    try
                    {
                        equipmentRecordService.RunEquipmentRecordTotal();
                    }
                    catch (Exception ex) 
                    {
                        ex.WriteErrorLog("设备记录统计异常");
                    }
                   
                    Thread.Sleep(1000 * 1800);
                }
            });
        }

        //记录设备数据
        private void RunEquipmentRecord()
        {
            try
            {
                var models = new List<EquipmentRecordUpdateModel>();
                foreach (var monitor in monitors)
                {
                    if (!monitor.IsRun)
                    {
                        continue;
                    }
                    var points = monitor.Points;
                    if (points.IsNullOrEmpty())
                    {
                        continue;
                    }

                    var equipmentIds = points.Select(f => f.EquipmentId).Distinct();
                    foreach (var id in equipmentIds)
                    {
                        var list = points.Where(f => f.EquipmentId == id).ToList();
                        if (list.Count >= 2)
                        {
                            var startStop = list.Where(f => f.ActionType == ActionType.StartStop).FirstOrDefault();
                            var fault = list.Where(f => f.ActionType == ActionType.Fault).FirstOrDefault();
                            if (!startStop.IsNullOrEmpty() &&
                                !fault.IsNullOrEmpty() &&
                                !startStop.ObjectValue.IsNullOrEmpty() &&
                                !fault.ObjectValue.IsNullOrEmpty())
                            {
                                var state = EquipmentState.Stop;
                                //如果运行状态比警告状态高，这里先判断运行状态，如果运行状态为false，在判断警告状态
                                if (startStop.GetValue<bool>())
                                {
                                    state = EquipmentState.Run;
                                }
                                else if (fault.GetValue<bool>())
                                {
                                    state = EquipmentState.Alarm;
                                   
                                }
                                //如果为报警状态，则判断是否设为手动，且为不报警，则屏蔽报警信号,不做记录
                                if (state == EquipmentState.Alarm && 
                                    startStop.Model == EquipmentAlarmModel.Manual && 
                                    !startStop.IsAlarm)
                                {
                                    continue;
                                }
                                //equipmentRecordService.AddUpdateEquipmentRecord(id, state, DateTime.Now);

                                models.Add(new EquipmentRecordUpdateModel 
                                {
                                    EquipmentId=id,
                                    State=state,
                                    DateTime=DateTime.Now
                                });
                            }
                        }
                    }
                }
                if (models.Count > 0) 
                {
                    //批量更新
                    equipmentRecordService.AddUpdateEquipmentRecordBatch(models);
                }

            }
            catch (Exception ex)
            {
                ex.WriteErrorLog("记录设备数据异常");
            }
        }

        private void DeviceMonitor_PointChnage(object sender, DevicePoint e)
        {

        }

        private void DeviceMonitor_ErrorMessage(object sender, string e)
        {
            e.WriteErrorLog();
        }
    }
}
