using CowainHmi.UIEditor;
using PCHMI;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Design;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Timers;
using System.Windows.Forms;
using static System.Net.Mime.MediaTypeNames;

namespace CowainHmi.Alarm
{
    public partial class AlarmNow : UserControl
    {
        private string fileName = "";
        [Browsable(true)]
        [Category("PCHMI"), Description("设置报警文件名称")]
        [Editor(typeof(AlarmUIEditor), typeof(UITypeEditor))]
        public string FileName
        {
            get
            {
                return this.fileName;
            }
            set
            {
                this.fileName = value;
            }
        }

        private bool autoShow = true;

        [Category("PCHMI"), Description("是否自动弹出报警窗口")]
        public bool AutoShow
        {
            get
            {
                return autoShow;
            }
            set
            {
                autoShow = value;
            }
        }

        private bool linkErrEnable;

        [Category("PCHMI"), Description("通讯报警是否捕获")]
        public bool LinkErrEnable
        {
            get
            {
                return linkErrEnable;
            }
            set
            {
                linkErrEnable = value;
            }
        }


        private string upLoadAddr = "";
        [Category("PCHMI"), Description("数据上传命令地址")]
        [Editor(typeof(StringText), typeof(UITypeEditor))]
        public string UpLoadAddr
        {
            get
            {
                return upLoadAddr;
            }
            set
            {
                upLoadAddr = value;
            }
        }
        private string upCountAddr = "";
        [Category("PCHMI"), Description("数据上传计数地址")]
        [Editor(typeof(StringText), typeof(UITypeEditor))]
        public string UpCountAddr
        {
            get
            {
                return upCountAddr;
            }
            set
            {
                upCountAddr = value;
            }
        }
        private string levelAddr = "";
        [Category("PCHMI"), Description("报警等级地址")]
        [Editor(typeof(StringText), typeof(UITypeEditor))]
        public string LevelAddr
        {
            get
            {
                return levelAddr;
            }
            set
            {
                levelAddr = value;
            }
        }
        private string groupAddr = "";
        [Category("PCHMI"), Description("报警组地址")]
        [Editor(typeof(StringText), typeof(UITypeEditor))]
        public string GroupAddr
        {
            get
            {
                return groupAddr;
            }
            set
            {
                groupAddr = value;
            }
        }
        private string idAddr = "";
        [Category("PCHMI"), Description("报警ID地址")]
        [Editor(typeof(StringText), typeof(UITypeEditor))]
        public string IdAddr
        {
            get
            {
                return idAddr;
            }
            set
            {
                idAddr = value;
            }
        }
        private string sd1Addr = "";
        [Category("PCHMI"), Description("报警SD1地址")]
        [Editor(typeof(StringText), typeof(UITypeEditor))]
        public string Sd1Addr
        {
            get
            {
                return sd1Addr;
            }
            set
            {
                sd1Addr = value;
            }
        }
        private string sd2Addr = "";
        [Category("PCHMI"), Description("报警SD2地址")]
        [Editor(typeof(StringText), typeof(UITypeEditor))]
        public string Sd2Addr
        {
            get
            {
                return sd2Addr;
            }
            set
            {
                sd2Addr = value;
            }
        }
        private string sd3Addr = "";
        [Category("PCHMI"), Description("报警SD3地址")]
        [Editor(typeof(StringText), typeof(UITypeEditor))]
        public string Sd3Addr
        {
            get
            {
                return sd3Addr;
            }
            set
            {
                sd3Addr = value;
            }
        }
        private string errTextAddr = "";
        [Category("PCHMI"), Description("报警文本地址")]
        [Editor(typeof(StringText), typeof(UITypeEditor))]
        public string ErrTextAddr
        {
            get
            {
                return errTextAddr;
            }
            set
            {
                errTextAddr = value;
            }
        }

        private string retAddr = "";
        [Category("PCHMI"), Description("报警反馈命令地址")]
        [Editor(typeof(StringText), typeof(UITypeEditor))]
        public string RetAddr
        {
            get
            {
                return retAddr;
            }
            set
            {
                retAddr = value;
            }
        }
        private string retCountAddr = "";
        [Category("PCHMI"), Description("报警反馈计数地址")]
        [Editor(typeof(StringText), typeof(UITypeEditor))]
        public string RetCountAddr
        {
            get
            {
                return retCountAddr;
            }
            set
            {
                retCountAddr = value;
            }
        }

        private int plcId = 0;
        [Category("PCHMI"), Description("PLC编号")]
        public int PLCId
        {
            get
            {
                return plcId;
            }
            set
            {
                plcId = value;
            }
        }

        public int ErrorCount { get; private set; }
        public bool Error { get; private set; }
        private int retCountSave;
        private bool newError;
        private bool chgError;
        private DataTable _errTable = new DataTable();
        private List<AlarmModel> _errList = new List<AlarmModel>();
        public AlarmNow()
        {
            InitializeComponent();
            _errTable.Columns.Add("PLC", typeof(string));
            _errTable.Columns.Add("DTIM", typeof(string));
            _errTable.Columns.Add("报警类别", typeof(string));
            _errTable.Columns.Add("报警组", typeof(string));
            _errTable.Columns.Add("ID", typeof(string));
            _errTable.Columns.Add("ErrText", typeof(string));
            _errTable.Columns.Add("TP", typeof(string));
            // 确保控件重绘时调用OnPaint  
            this.SetStyle(ControlStyles.OptimizedDoubleBuffer | ControlStyles.ResizeRedraw | ControlStyles.AllPaintingInWmPaint, true);
        }

        private void AlarmNow_Load(object sender, EventArgs e)
        {
            if (string.IsNullOrEmpty(FileName))
            {
                FileName = this.Name;
            }
            InitErrExcel();
            //刚打开时加载实时报警表格
            var rt = AlarmExcelHelper.GetAlarmRT(FileName);
            if (rt != null)
            {
                var list = rt.Select("TP='1'");
                foreach (var item in list)
                {
                    _errTable.Rows.Add(item.ItemArray);
                }
            }
            //初始读一次，相当于注册变量
            ushort level = PCHMI.RT.GET_UINT16(PLCId, LevelAddr);
            ushort group = PCHMI.RT.GET_UINT16(PLCId, GroupAddr);
            int id = PCHMI.RT.GET_UINT16(PLCId, IdAddr) + 10000;
            short sd1 = PCHMI.RT.GET_INT16(PLCId, Sd1Addr);
            int sd2 = PCHMI.RT.GET_INT32(PLCId, Sd2Addr);
            float sd3 = PCHMI.RT.GET_F32(PLCId, Sd3Addr);
            string errText = PCHMI.RT.GET_SIEMENS_STRING(PLCId, ErrTextAddr, 100);
            ushort count = PCHMI.RT.GET_UINT16(PLCId, UpCountAddr);
            short upLoad = PCHMI.RT.GET_INT16(PLCId, UpLoadAddr);
            timer1.Enabled = true;
        }

        private void InitErrExcel()
        {
            if (!string.IsNullOrEmpty(FileName))
            {
                //读取报警表格文件
                DataTable _errExcel = AlarmExcelHelper.ReadErrExcel(FileName);
                if (_errExcel != null && _errExcel.Rows.Count > 0)
                {
                    for (int i = 0; i < _errExcel.Rows.Count; i++)
                    {
                        DataRow row = _errExcel.Rows[i];
                        AlarmModel model = new AlarmModel();
                        model.PLC = Convert.ToInt32(row["PLC"]);
                        model.VarType = row["类型"].ToString();
                        model.Address = row["地址"].ToString();
                        model.ErrCode = row["代码"].ToString();
                        model.Level = row["等级"].ToString();
                        model.Language = new string[] {
                            row["语言1"].ToString(),
                            row["语言2"].ToString(),
                            row["语言3"].ToString(),
                            row["语言4"].ToString(),
                            row["语言5"].ToString(),
                            row["语言6"].ToString(),
                            row["语言7"].ToString(),
                            row["语言8"].ToString()
                        };
                        if (!int.TryParse(row["触发条件"].ToString(), out int tp))
                        {
                            continue;
                        }
                        model.TP = tp;
                        if (!int.TryParse(row["报警组"].ToString(), out int group))
                        {
                            continue;
                        }
                        model.Group = group;
                        _errList.Add(model);
                    }
                }
            }
        }

        private bool isFlg = false;
        private void timer1_Tick(object sender, EventArgs e)
        {
            if (isFlg)
            {
                return;
            }
            isFlg = true;
            if (this.DesignMode)
            {
                return;
            }
            if (!PClass.SystemRun)
            {
                return;
            }
            //通讯报警
            if (LinkErrEnable)
            {
                for (int i = 0; i < 10; i++)
                {
                    if (!PClass.IsPlcLink(i))
                    {
                        //报警发生，查询表格中是否存在此报警
                        var dr = _errTable.Select($"报警类别='{AlarmType.错误.ToString()}' and 报警组='S' and ID='0'").FirstOrDefault();
                        if (dr == null)
                        {
                            //添加报警到table中
                            _errTable.Rows.Add(new object[]
                                                   {
                                            PLCId.ToString(),
                                            DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss:fffff"),
                                           AlarmType.错误.ToString(),//错误类型
                                            "S",//组
                                            "0",//ID
                                            $"PLC{PLCId},连接异常",  //错误信息
                                            "1"
                                                   });
                            newError = true;
                        }
                    }
                    else
                    {
                        //通讯报警离开
                        var dr = _errTable.Select($"报警类别='{AlarmType.错误.ToString()}' and 报警组='S' and ID='0'").FirstOrDefault();
                        if (dr != null)
                        {
                            //删除报警
                            _errTable.Rows.Remove(dr);
                        }
                    }
                }
            }

            if (PClass.IsPlcLink(PLCId) && !string.IsNullOrEmpty(UpLoadAddr))
            {
                //循环读数据,PLC主动上传报警
                ushort level = PCHMI.RT.GET_UINT16(PLCId, LevelAddr);
                ushort group = PCHMI.RT.GET_UINT16(PLCId, GroupAddr);
                int id = PCHMI.RT.GET_UINT16(PLCId, IdAddr) + 10000;
                short sd1 = PCHMI.RT.GET_INT16(PLCId, Sd1Addr);
                int sd2 = PCHMI.RT.GET_INT32(PLCId, Sd2Addr);
                float sd3 = PCHMI.RT.GET_F32(PLCId, Sd3Addr);
                string errText = PCHMI.RT.GET_SIEMENS_STRING(PLCId, ErrTextAddr, 100);
                ushort count = PCHMI.RT.GET_UINT16(PLCId, UpCountAddr);
                short upLoad = PCHMI.RT.GET_INT16(PLCId, UpLoadAddr);
                if (retCountSave != count && upLoad > 0)
                {
                    //计数改变，需要上传数据

                    string errMsg = errText.Replace("{1}", sd1.ToString()).Replace("{2}", sd2.ToString()).Replace("{3}", sd3.ToString());
                    string alarmType = ((AlarmType)level).ToString();
                    if (upLoad == 1)
                    {
                        //报警发生,添加报警，还需要写到实时数据库中
                        var dr = _errTable.Select($"报警类别='{alarmType}' and 报警组='{group}' and ID='{id}'").FirstOrDefault();
                        if (dr == null)
                        {
                            _errTable.Rows.Add(new object[]
                                      {
                                            PLCId.ToString(),
                                            DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss:fffff"),
                                            alarmType,//错误类型
                                            group.ToString(),//组
                                            id.ToString(),//ID
                                            errMsg,  //错误信息
                                            "1"
                                      });
                            AlarmExcelHelper.UpdateAlarmRT(PLCId.ToString(), alarmType, group.ToString(), id.ToString(), errMsg, true, FileName);
                            AlarmExcelHelper.SaveAlarmLog(PLCId.ToString(), alarmType, group.ToString(), id.ToString(), "1", errMsg);
                        }
                        PCHMI.RT.SEND_UINT16(PLCId, RetAddr, 1);
                        PCHMI.RT.SEND_UINT16(PLCId, RetCountAddr, count);
                        retCountSave = count;
                        newError = true;
                    }
                    else if (upLoad == 2)
                    {
                        //报警离开
                        var dr = _errTable.Select($"报警类别='{alarmType}' and 报警组='{group}' and ID='{id}'").FirstOrDefault();
                        if (dr != null)
                        {
                            _errTable.Rows.Remove(dr);
                            AlarmExcelHelper.UpdateAlarmRT(PLCId.ToString(), alarmType, group.ToString(), id.ToString(), errMsg, false, FileName);
                            AlarmExcelHelper.SaveAlarmLog(PLCId.ToString(), alarmType, group.ToString(), id.ToString(), "0", errMsg);
                        }
                        PCHMI.RT.SEND_UINT16(PLCId, RetAddr, 1);
                        PCHMI.RT.SEND_UINT16(PLCId, RetCountAddr, count);
                        retCountSave = count;
                    }
                }
            }
            if (_errList.Count > 0)
            {
                //判断报警表格中是否有报警发生
                foreach (var alarmModel in _errList)
                {
                    if (CONFIG.PLC_OFF[alarmModel.PLC])
                    {
                        continue;
                    }
                    switch (alarmModel.VarType)
                    {
                        case "BIT":
                            alarmModel.CurValue = (int)PCHMI.RT.GET_BIT(alarmModel.PLC, alarmModel.Address);
                            break;
                        case "INT16":
                            alarmModel.CurValue = (int)PCHMI.RT.GET_INT16(alarmModel.PLC, alarmModel.Address);
                            break;
                        case "UINT16":
                            alarmModel.CurValue = (int)PCHMI.RT.GET_UINT16(alarmModel.PLC, alarmModel.Address);
                            break;
                        case "INT32":
                            alarmModel.CurValue = PCHMI.RT.GET_INT32(alarmModel.PLC, alarmModel.Address);
                            break;
                        case "UINT32":
                            alarmModel.CurValue = (int)PCHMI.RT.GET_UINT32(alarmModel.PLC, alarmModel.Address);
                            break;
                        default:
                            break;
                    }
                    if (alarmModel.CurValue != alarmModel.LastValue)
                    {
                        //值改变
                        if (alarmModel.CurValue == alarmModel.TP)
                        {
                            //报警发生
                            var dr = _errTable.Select($"报警类别='{alarmModel.Level}' and 报警组='{alarmModel.Group}' and ID='{alarmModel.ErrCode}'").FirstOrDefault();
                            if (dr == null)
                            {
                                _errTable.Rows.Add(new object[]
                                          {
                                            PLCId.ToString(),
                                            DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss:fffff"),
                                            alarmModel.Level,//错误类型
                                            alarmModel.Group.ToString(),//组
                                            alarmModel.ErrCode.ToString(),//ID
                                            alarmModel.Language[GLOBAL.Language],  //错误信息
                                            "1"
                                          });
                                //AlarmExcelHelper.UpdateAlarmRT(PLCId.ToString(), alarmModel.Level, alarmModel.Group.ToString(), alarmModel.ErrCode.ToString(), alarmModel.Language[GLOBAL.Language], true, FileName);
                                AlarmExcelHelper.SaveAlarmLog(PLCId.ToString(), alarmModel.Level, alarmModel.Group.ToString(), alarmModel.ErrCode.ToString(), "1", alarmModel.Language[GLOBAL.Language]);
                                newError = true;
                            }
                        }
                        else
                        {
                            //报警离开
                            var dr = _errTable.Select($"报警类别='{alarmModel.Level}' and 报警组='{alarmModel.Group.ToString()}' and ID='{alarmModel.ErrCode.ToString()}'").FirstOrDefault();
                            if (dr != null)
                            {
                                _errTable.Rows.Remove(dr);
                                //AlarmExcelHelper.UpdateAlarmRT(PLCId.ToString(), alarmModel.Level, alarmModel.Group.ToString(), alarmModel.ErrCode.ToString(), alarmModel.Language[GLOBAL.Language], false, FileName);
                                AlarmExcelHelper.SaveAlarmLog(PLCId.ToString(), alarmModel.Level, alarmModel.Group.ToString(), alarmModel.ErrCode.ToString(), "0", alarmModel.Language[GLOBAL.Language]);
                            }
                        }
                    }
                    alarmModel.LastValue = alarmModel.CurValue;
                }
            }

            ErrorCount = _errTable.Rows.Count;
            Error = ErrorCount > 0 ? true : false;
            if (Error)
            {
                //有报警
                chgError = !chgError;
                //控制报警图标闪烁
                this.BackgroundImage = chgError ? global::CowainHmi.Properties.Resources.alarm1 : global::CowainHmi.Properties.Resources.Alarm;
                if (newError & this.AutoShow)
                {
                    //有新报警出现,自动弹窗
                    ShowErrDlg();
                }
            }
            else
            {
                //无报警
                this.BackgroundImage = global::CowainHmi.Properties.Resources.alarm1;
            }
            isFlg = false;
        }

        DlgAlarmNow dlgAlarm;
        private void ShowErrDlg()
        {
            //弹出报警窗口
            if (dlgAlarm == null)
            {
                dlgAlarm = new DlgAlarmNow(_errTable);
            }
            dlgAlarm.Show();    //显示窗体
            dlgAlarm.WindowState = FormWindowState.Normal;
            dlgAlarm.Activate();
            newError = false;
        }
        private void AlarmNow_MouseDown(object sender, MouseEventArgs e)
        {
            ShowErrDlg();
        }


        protected override void OnPaint(PaintEventArgs e)
        {
            base.OnPaint(e);
            if (ErrorCount == 0)
            {
                return;
            }
            using (Brush brush = new SolidBrush(ForeColor))
            {
                // 获取Graphics对象  
                Graphics g = e.Graphics;
                // 获取控件的绘制区域  
                // 计算字符串绘制的起始位置（控件的右上角，留出一些内边距）  
                //PointF textPosition = new PointF(this.Width - g.MeasureString(ErrorCount.ToString(), this.Font).Width - padding, padding);
                PointF textPosition = new PointF(1, 7);
                // 设置字符串格式，这里我们使用StringFormat来居中字符串  
                StringFormat sf = new StringFormat();
                sf.Alignment = StringAlignment.Near;
                sf.LineAlignment = StringAlignment.Center;
                g.DrawString(ErrorCount.ToString(), this.Font, brush, textPosition, sf);
                sf.Dispose();
            }

        }

       
    }
}
