using AntdUI;
using AntdUI.Svg;
using DH.Commons.Base;
using DH.Commons.Enums;
using DH.Commons.Helper;
using DH.Commons.Models;
using DH.Devices.Camera;
using DH.Devices.Motion;
using DH.Devices.PLC;
using DH.Devices.Vision;
using DHSoftware.Languages;
using DHSoftware.Models;
using DHSoftware.Utils;
using DHSoftware.Views;
using DVPCameraType;
using HalconDotNet;
using Microsoft.VisualBasic.Logging;
using Microsoft.Win32;
using OpenCvSharp;
using SqlSugar;
using System;
using System.CodeDom;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Drawing;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using XKRS.UI.Device.Winform;
using static AntdUI.Math3D;
using static DH.Commons.Enums.EnumHelper;
using Camera = DHSoftware.Models.Camera;
using LogLevel = DH.Commons.Enums.EnumHelper.LogLevel;
using ResultState = DH.Commons.Base.ResultState;
using Timer = System.Threading.Timer;

namespace DHSoftware
{
    public partial class MainWindow : AntdUI.Window
    {
        System.Windows.Forms.Timer _refreshUITimer = new System.Windows.Forms.Timer();
        private Dictionary<string, List<string>> _cameraRelatedDetectionDict = null;
        public event Action<LogMsg> OnLog;

        public List<CameraSummary> CameraSummaries { get; set; } = new List<CameraSummary>();
        public List<ProductSummary> ProductSummaries { get; set; } = new List<ProductSummary>();
        static object _productSummaryLock = new object();
        public event Action<DateTime, object, string> OnUpdateResult;
        public event Action<DateTime, object, string> OnUpdateCamResult;

        private string _loginName;

        public string LoginName
        {
            get { return _loginName; }
            set
            {
                _loginName = value;
                UpdateLabel();
            }
        }

        private bool _ShowConfig;

        public bool ShowConfig
        {
            get { return _ShowConfig; }
            set
            {
                _ShowConfig = value;
                UpdateConfig();
            }
        }

        private bool _addscheme;

        public bool Addscheme
        {
            get { return _addscheme; }
            set
            {
                _addscheme = value;
                UpdateScheme();
            }
        }

        private bool _deletescheme;

        public bool Deleteschememe
        {
            get { return _deletescheme; }
            set
            {
                _deletescheme = value;
                UpdateScheme();
            }
        }

        private bool _loadscheme;

        public bool Loadscheme
        {
            get { return _loadscheme; }
            set
            {
                _loadscheme = value;
                UpdateScheme();
            }
        }

        private void UpdateScheme()
        {
            if (this.InvokeRequired)
            {
                this.Invoke(new Action(UpdateScheme));
                return;
            }

            if (Loadscheme)
            {
                btnDeleteProject.Visible = true;
            }
            else
            {
                btnDeleteProject.Visible = false;
            }
            if (Addscheme)
            {
                btnAddProject.Visible = true;
            }
            else
            {
                btnAddProject.Visible = false;
            }
            if (Deleteschememe)
            {
                btnLoadProject.Visible = true;
            }
            else
            {
                btnLoadProject.Visible = false;
            }
        }

        private void UpdateLabel()
        {
            if (lbName.InvokeRequired)
            {
                lbName.Invoke(new Action(UpdateLabel));
                return;
            }
            lbName.Text = _loginName;
        }

        private void UpdateConfig()
        {
            if (ShowConfig)
            {
                if (segmented1.InvokeRequired)
                {
                    segmented1.Invoke(new Action(UpdateConfig));
                    return;
                }
                // 恢复显示时
                segmented1.Items.Insert(4, itemToHide);
            }
            else
            {
                if (segmented1.InvokeRequired)
                {
                    segmented1.Invoke(new Action(UpdateConfig));
                    return;
                }
                segmented1.Items.Remove(itemToHide);
            }
        }

        public MainWindow()
        {
            InitializeComponent();
            InitialCameraSumsView();            //refreshTimer.Start();
            //初始化数据
            InitData();
            //绑定事件
            BindEventHandler();
            //UserConfigFrm userControlFrm = new UserConfigFrm();

            //userControlFrm.Window = this;
            //userControlFrm.Dock = DockStyle.Fill;
            //tabPage2.Controls.Add(userControlFrm);
        }
        //#region OEE
        // public event Action<RunState> OnProcessRunStateChanged;
        #region INotifyPropertyChanged
        public event PropertyChangedEventHandler PropertyChanged;
        public virtual void Set<T>(ref T field, T newValue, [CallerMemberName] string propName = null)
        {
            if (!field.Equals(newValue))
            {
                field = newValue;
                PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propName));
            }
        }
        #endregion
        #region Properties
        private int uph = 0;
        private int upm = 0;

        private DateTime? startTime = null;
        private TimeSpan runTime = new TimeSpan();
        private TimeSpan idleTime = new TimeSpan();
        private TimeSpan downTime = new TimeSpan();
        private TimeSpan totalTime = new TimeSpan();
        private int qty_OEE = 0;
        private int qty_OEE_OK = 0;
        private float oee = 0;

        public int UPH
        {
            get => uph;
            set => Set(ref uph, value);
        }
        public int UPM
        {
            get => upm;
            set => Set(ref upm, value);
        }
        public DateTime? StartTime
        {
            get => startTime;
            set => Set(ref startTime, value);
        }

        /// <summary>
        /// 有效运行时间
        /// </summary>
        public TimeSpan RunTime
        {
            get => runTime;
            set => Set(ref runTime, value);
        }

        /// <summary>
        /// 空闲待机时间
        /// </summary>
        public TimeSpan IdleTime
        {
            get => idleTime;
            set => Set(ref idleTime, value);
        }

        /// <summary>
        /// 故障宕机时间
        /// </summary>
        public TimeSpan DownTime
        {
            get => downTime;
            set => Set(ref downTime, value);
        }

        /// <summary>
        /// 总开机时间
        /// </summary>
        public TimeSpan TotalTime
        {
            get => totalTime;
            set => Set(ref totalTime, value);
        }

        public float OEE
        {
            get => oee;
            set => Set(ref oee, value);
        }
        #endregion
        #region Timer
        System.Threading.Timer _runTimer = null;
        System.Threading.Timer _idleTimer = null;
        System.Threading.Timer _downTimer = null;
        System.Threading.Timer _checkIdleTimer = null;
        //System.Threading.Timer _calculateTimer = null;

        private RunState? currentState = null;
        public RunState? CurrentState
        {
            get => currentState;
            set
            {
                if (value != null)
                {
                    if (value.Value == RunState.Running)
                    {
                        _checkIdleTimer?.Change(10 * 1000, -1);
                    }

                    if (currentState != value.Value)
                    {
                        switch (currentState)
                        {
                            case RunState.Idle:
                                //AddRunEventInBuffer(DateTime.Now, RunEvent_EventType.Idle, false);
                                break;
                            case RunState.Down:
                                //AddRunEventInBuffer(DateTime.Now, RunEvent_EventType.Down, false);
                                break;
                        }

                        switch (value.Value)
                        {
                            case RunState.Stop:
                                _runTimer?.Change(-1, -1);
                                _idleTimer?.Change(-1, -1);
                                _downTimer?.Change(-1, -1);
                                break;
                            case RunState.Running:
                                _idleTimer?.Change(-1, -1);
                                _downTimer?.Change(-1, -1);
                                _runTimer?.Change(0, 1000);
                                break;
                            case RunState.Idle:
                                _runTimer?.Change(-1, -1);
                                _downTimer?.Change(-1, -1);
                                _idleTimer?.Change(0, 1000);

                                //AddRunEventInBuffer(DateTime.Now, RunEvent_EventType.Idle, true);
                                break;
                            case RunState.Down:
                                _idleTimer?.Change(-1, -1);
                                _runTimer?.Change(-1, -1);
                                _downTimer?.Change(0, 1000);

                                //AddRunEventInBuffer(DateTime.Now, RunEvent_EventType.Down, true);
                                break;
                        }

                        currentState = value;

                        
                    }
                }
            }
        }

        private void CheckIdleTimeStart(object state)
        {
            if (CurrentState == RunState.Running)
            {
                RunTime = RunTime.Add(new TimeSpan(0, 0, 0 - 10));
                IdleTime = IdleTime.Add(new TimeSpan(0, 0, 10));

                CurrentState = RunState.Idle;
            }
        }

        public void InitialOEEStatistic()
        {
            InitialStatisticTimers();
            ResetOEETimeDistribute();
            ResetProductSummaries();
        }

        public void ResetProductSummaries()
        {
            ProductSummaries = new List<ProductSummary>();
        }
        private void InitialStatisticTimers()
        {
            if (_checkIdleTimer == null)
            {
                _checkIdleTimer = new Timer(new TimerCallback(CheckIdleTimeStart), null, -1, -1);
            }

            if (_runTimer == null)
            {
                _runTimer = new System.Threading.Timer(RunTimerCallBack, null, -1, -1);
            }

            if (_idleTimer == null)
            {
                _idleTimer = new System.Threading.Timer(IdleTimerCallBack, null, -1, -1);
            }

            if (_downTimer == null)
            {
                _downTimer = new System.Threading.Timer(DownTimerCallBack, null, -1, -1);
            }

            StartTime = DateTime.Now;
            DownTime = IdleTime = RunTime = new TimeSpan(0, 0, 0);
            CurrentState = RunState.Running;
        }

        private void DownTimerCallBack(object state)
        {
            DownTime = DownTime.Add(new TimeSpan(0, 0, 1));
            GetTotalTime();
        }

        private void IdleTimerCallBack(object state)
        {
            IdleTime = IdleTime.Add(new TimeSpan(0, 0, 1));
            GetTotalTime();
        }

        private void RunTimerCallBack(object state)
        {
            RunTime = RunTime.Add(new TimeSpan(0, 0, 1));
            GetTotalTime();
        }

        private void GetTotalTime()
        {
            TotalTime = RunTime + IdleTime + DownTime;
        }

        public void ResetOEETimeDistribute()
        {
            StartTime = DateTime.Now;
            DownTime = IdleTime = RunTime = new TimeSpan(0, 0, 0);

            ProductNum_Total = ProductNum_OK = 0;
        }

        public void CloseStatisticTimers()
        {
            CloseTimer(ref _checkIdleTimer);
            CloseTimer(ref _runTimer);
            CloseTimer(ref _idleTimer);
            CloseTimer(ref _downTimer);

            CurrentState = RunState.Stop;
        }

        private void CloseTimer(ref System.Threading.Timer timer)
        {
            timer?.Change(-1, -1);
            timer?.Dispose();
            timer = null;
        }
        #endregion

        #region CameraSum
        private void InitialCameraSumsView()
        {
            dgvProductNums.AutoGenerateColumns = false;

            dgvProductNums.DefaultCellStyle.Font = new Font("Tahoma", 12, FontStyle.Regular, GraphicsUnit.World);

            dgvProductNums.DataSource = null;
            dgvProductNums.DataSource = ProductSummaries;


            dgvCamreaNums.AutoGenerateColumns = false;

            dgvCamreaNums.DefaultCellStyle.Font = new Font("Tahoma", 12, FontStyle.Regular, GraphicsUnit.World);

            dgvCamreaNums.DataSource = null;
            dgvCamreaNums.Columns.Clear();

            // 添加 CCD 列
            dgvCamreaNums.Columns.Add(new DataGridViewTextBoxColumn
            {
                HeaderText = "CCD",
                DataPropertyName = "CameraName"
            });

            // 添加 合格 列
            var okColumn = new DataGridViewTextBoxColumn
            {
                HeaderText = "合格",
                DataPropertyName = "OKCount"
            };
            okColumn.DefaultCellStyle.ForeColor = Color.LightGreen; // 设置背景为绿色
            dgvCamreaNums.Columns.Add(okColumn);

            // 添加 不合格 列
            var ngColumn = new DataGridViewTextBoxColumn
            {
                HeaderText = "不合格",
                DataPropertyName = "NGCount"
            };
            ngColumn.DefaultCellStyle.ForeColor = Color.LightCoral; // 设置背景为红色
            dgvCamreaNums.Columns.Add(ngColumn);

            // 添加 总数 列
            dgvCamreaNums.Columns.Add(new DataGridViewTextBoxColumn
            {
                HeaderText = "总数",
                DataPropertyName = "TotalCount"

            });

            // 添加 良率 列
            dgvCamreaNums.Columns.Add(new DataGridViewTextBoxColumn
            {
                HeaderText = "良率",
                DataPropertyName = "YieldStr"
            });

            dgvCamreaNums.DataSource = new BindingList<CameraSummary>(CameraSummaries);
        }
        #endregion

        /// <summary>
        /// 窗体对象实例
        /// </summary>
        private static MainWindow _instance;

        internal static MainWindow Instance
        {
            get
            {
                if (_instance == null)
                    _instance = new MainWindow();
                return _instance;
            }
        }

        private SegmentedItem itemToHide;

        private void InitData()
        {
            itemToHide = segmented1.Items[4];
            segmented1.Items.Remove(itemToHide);
        }

        public void LoadScheme()
        {
            try
            {
                //方案配置初始化
                SchemeHelper.Initialize();
                //读取方案列表
                List<string> list = SchemeHelper.GetAllSchemes();
                string CurrentScheme = "默认方案";
                //如果是空,新增默认数据
                if (list == null || list.Count <= 0)
                {
                    list = new() { CurrentScheme };
                    //显示到方案列表
                    sltProjects.Items.Clear();

                    sltProjects.Items.Add(CurrentScheme);
                    //保存到方案配置
                    SchemeHelper.AddScheme(CurrentScheme);
                    SchemeHelper.SetCurrentScheme(CurrentScheme);
                    //新构建配置文件
                    ConfigHelper.InitializeScheme(CurrentScheme);

                    sltProjects.SelectedIndex = 0;
                }
                else
                {
                    foreach (string s in list)
                    {
                        sltProjects.Items.Add(s);
                    }
                    CurrentScheme = SchemeHelper.GetCurrentScheme();
                    sltProjects.SelectedValue = CurrentScheme;
                }
                SystemModel.CurrentScheme = CurrentScheme;
                //加载当前方案配置
                ConfigHelper.LoadConfig();
            }
            catch (Exception ex)
            {
                AntdUI.Message.error(this, ex.Message, autoClose: 3);
            }
        }

        public void ConnectCamera()
        {
            Cameras.Clear();
            HKCameras.Clear();
            if (ConfigModel.CameraBaseList.Count > 0)
            {
                for (int i = 0; i < ConfigModel.CameraBaseList.Count; i++)
                {
                    var cameraBase = ConfigModel.CameraBaseList[i];
                    if (cameraBase.CamType == EnumCamType.度申Do3think)
                    {

                    
                        Do3ThinkCamera cam =new  Do3ThinkCamera();
                        cam.IsSavePicEnabled = cameraBase.IsSavePicEnabled;
                        cam.CameraName = cameraBase.CameraName;
                        cam.CameraIP = cameraBase.CameraIP;
                        cam.IsEnabled = cameraBase.IsEnabled;
                        cam.ImageSaveDirectory = "D://Cam1//";
                        Cameras.Add(cam);
                        if(cameraBase.IsEnabled)
                        {
                            cam.OnLog -= _visionEngine_OnLog;
                            cam.OnLog += _visionEngine_OnLog;
                            cam.CameraConnect();
                            cam.OnHImageOutput += OnCameraHImageOutput;
                        }
                       
                    }
                    else if (cameraBase.CamType == EnumCamType.海康hik)
                    {
                        HikVisionCamera cam = new HikVisionCamera();
                        cam.CameraName = cameraBase.CameraName;
                        cam.CameraIP = cameraBase.CameraIP;
                        cam.IsEnabled = cameraBase.IsEnabled;
                        HKCameras.Add(cam);
                        // cam.CameraConnect();
                        cam.OnHImageOutput += OnCameraHImageOutput;
                    }
                }
            }
        }

        public void ConnectPLC()
        {
            if (ConfigModel.PLCBaseList.Count > 0)
            {
                for (int i = 0; i < ConfigModel.PLCBaseList.Count; i++)
                {
                    var plcBase = ConfigModel.PLCBaseList[i];
                    if (plcBase.PLCType == EnumPLCType.信捷XC网口 || plcBase.PLCType == EnumPLCType.信捷XD网口)
                    {
                        PLC.IP = plcBase.IP;
                        PLC.PLCType = plcBase.PLCType;
                        PLC.Enable = plcBase.Enable;
                        PLC.PLCName = plcBase.PLCName;
                        PLC.PLCItemList = plcBase.PLCItemList;
                        PLC.Port = plcBase.Port;
                        PLC.OnLog -= _visionEngine_OnLog;
                        PLC.OnLog += _visionEngine_OnLog;
                        PLC.PLCConnect();
                    }
                }
            }
        }
        FrmLog frmLog;
        public void InitModel()
        {
            Dectection.Clear();
            _cameraRelatedDetectionDict = new();

            if (ConfigModel.DetectionList.Count > 0)
            {
                for (int i = 0; i < ConfigModel.DetectionList.Count; i++)
                {
                    DetectionConfig detectionConfig = ConfigModel.DetectionList[i];
                    var detection = ConfigModel.DetectionList[i];
                    detectionConfig.CameraCollects = detection.CameraCollects;
                    detectionConfig.ModelconfThreshold = detection.ModelconfThreshold;
                    detectionConfig.ModelWidth = detection.ModelWidth;
                    detectionConfig.ModelHeight = detection.ModelHeight;
                    detectionConfig.In_lable_path = detection.In_lable_path;
                    detectionConfig.IsEnabled = detection.IsEnabled;
                   
                    detectionConfig.ShowLocation.X = (i + 1) % 5 + (i + 1) / 5;
                    //  detectionConfig.ShowLocation.X = detection.ShowLocation.X;
                    detectionConfig.ShowLocation.Y = (i + 1) / 5 + 1;
                    // detectionConfig.ShowLocation.Y = detection.ShowLocation.Y;
                    DetectionConfigs.Add(detectionConfig);
                }
            }
            DetectionConfigs.ForEach(detection =>
            {
                detection.CameraCollects.ForEach(cam =>
                {
                    List<string> Dets = new List<string>
                   {
                        detection.Id
                   };
                    if (!_cameraRelatedDetectionDict.ContainsKey(cam.CameraSourceId))
                    {
                        _cameraRelatedDetectionDict.Add(cam.CameraSourceId, Dets);
                    }
                    else
                    {
                        _cameraRelatedDetectionDict[cam.CameraSourceId].Add(detection.Id);
                    }
                }
               );
            });
            string inferenceDevice = "CPU";

            frmLog = new FrmLog();
            frmLog.Dock = DockStyle.Fill;
            pnlLog.Controls.Add(frmLog);
            //
            _visionEngine = new SimboVisionDriver();
            _visionEngine.DetectionConfigs = DetectionConfigs;
            _visionEngine.OnLog += _visionEngine_OnLog;
            //初始化模型 加载模型
            _visionEngine.Init();

            CtrlVisionRunBase ctrlVisionRun = new CtrlVisionRunBase(_visionEngine);
            ctrlVisionRun.Dock = DockStyle.Fill;
            tabImgDisplay.Controls.Add(ctrlVisionRun);

        }

        private void _visionEngine_OnLog(LogMsg msg)
        {
            OnLog?.Invoke(msg);
            LogDisplay(msg);
        }
        private void LogDisplay(LogMsg msg)
        {
            
            frmLog?.LogDisplay(msg);
        }
        public LoggerHelper LoggerHelper { get; set; } = new LoggerHelper();
        public virtual void LogAsync(LogMsg msg)
        {
            //if (IConfig != null)
            //{
            //    LoggerHelper.SetLogLevel(IConfig.DefaultLogLevel);
            //}
            //else
            //{
            //    LoggerHelper.SetLogLevel(LogLevel.Assist);
            //}

            msg.ThreadId = Thread.CurrentThread.ManagedThreadId;

            OnLog?.Invoke(msg);
            //if (IConfig?.IsLogEnabled ?? true)
            //{
                LoggerHelper.LogAsync(msg);
            //}
        }
        public virtual void LogAsync(DateTime dt, LogLevel logLevel, string msg)
        {
            LogAsync(new LogMsg(dt, logLevel, msg));
            
        }
        private void BindEventHandler()
        {
            btnAddProject.Click += BtnAddProject_Click;
            btnDeleteProject.Click += BtnDeleteProject_Click;
            btnLoadProject.Click += BtnLoadProject_Click;
            LoggerHelper.LogPath = "D://";
            LoggerHelper.LogPrefix = "Process";
            OnLog -= LogDisplay;
            OnLog += LogDisplay;

            OnUpdateCamResult -= UpdateCamResult;

            OnUpdateCamResult += UpdateCamResult;
            OnUpdateResult -= UpdateResult;
            OnUpdateResult += UpdateResult;
            Load += (s, e) =>
            {
                _refreshUITimer.Interval = 1000;
                _refreshUITimer.Tick += _refreshUITimer_Tick;
                _refreshUITimer.Enabled = true;
            };
        }
        private void _refreshUITimer_Tick(object sender, EventArgs e)
        {
            _refreshUITimer.Enabled = false;

            if (this != null)
            {
                lblStartTime.Text = StartTime == null ? "" : StartTime.Value.ToString("yyyy/MM/dd HH:mm:ss");
                lblTotalTime.Text = TotalTime.ToString(); // 运行时间
               // lblRunTime.Text = RunTime.ToString(); // 有效时间
               // lblIdleTime.Text = ProcessControl.IdleTime.ToString(); // 空闲时间
               // lblDownTime.Text = ProcessControl.DownTime.ToString(); // 宕机时间

                lblOEE_Total.Text =ProductNum_Total.ToString();
                //lblOEE_OK.Text = ProcessControl.ProductNum_OK.ToString();
            }

            _refreshUITimer.Enabled = true;
        }
        private void UpdateCamResult(DateTime updateTime, object objData, string customMessage)
        {
            this.Invoke(new Action(() =>
            {

                BindingList<CameraSummary> cameraSummaries = new BindingList<CameraSummary>(CameraSummaries);
                dgvCamreaNums.DataSource = cameraSummaries;

            }));

        }
        private void UpdateResult(DateTime updateTime, object objData, string result)
        {
            this.Invoke(new Action(() =>
            {
                //dgvProductNums.DataSource = null;

                BindingList<ProductSummary> productSummaries = new BindingList<ProductSummary>(ProductSummaries);

                dgvProductNums.DataSource = productSummaries;

                //if (dgvProductNums.Rows.Count > 0)
                //{
                //    dgvProductNums.Height = dgvProductNums.Rows[0].Height * dgvProductNums.Rows.Count + 15;
                //}
                //else
                //{
                //    dgvProductNums.Height = 15;
                //}

                //lblOEE_Rate.Text = ProcessControl.OEE.ToString("f2") + " %";
                lblUPH.Text = UPH.ToString();
            }));
        }

        private void BtnDeleteProject_Click(object? sender, EventArgs e)
        {
            try
            {
                if (sltProjects.Items.Count == 0 || sltProjects.SelectedIndex == -1) return;

                var result = AntdUI.Modal.open(this, "删除警告!", "确认要删除该方案吗?", TType.Warn);
                if (result == DialogResult.OK)
                {
                    int selectedIndex = sltProjects.SelectedIndex;

                    // 删除当前选中项
                    SchemeHelper.DeleteScheme(sltProjects.Text);
                    ConfigHelper.DeleteSchemeConfig(sltProjects.Text);
                    AntdUI.Message.success(this, $"删除方案{sltProjects.Text}成功!", autoClose: 3);
                    sltProjects.Items.RemoveAt(selectedIndex);
                    // 自动选择下一个(如果存在)
                    if (sltProjects.Items.Count > 0)
                    {
                        // 如果删除的不是最后一项,则选中原位置的新项,否则选中最后一项
                        sltProjects.SelectedIndex = selectedIndex < sltProjects.Items.Count
                            ? selectedIndex
                            : sltProjects.Items.Count - 1;

                        SystemModel.CurrentScheme = sltProjects.Text;
                        SchemeHelper.SetCurrentScheme(SystemModel.CurrentScheme);
                        //加载当前方案配置
                        ConfigHelper.LoadConfig();
                    }
                    else
                    {
                        sltProjects.SelectedIndex = -1; // 清空选择
                        AntdUI.Modal.open(this, "空方案警告!", "当前方案全部删除,需重启程序!", TType.Warn);
                    }
                }
            }
            catch (Exception ex)
            {
                AntdUI.Message.error(this, ex.Message, autoClose: 3);
            }
        }

        private void BtnLoadProject_Click(object? sender, EventArgs e)
        {
            try
            {
                if (sltProjects.Items.Count == 0 || sltProjects.SelectedIndex == -1) return;
                if (SystemModel.CurrentScheme == sltProjects.Text)
                {
                    AntdUI.Message.warn(this, "当前已是该方案,无需重复载入!", autoClose: 3);
                    return;
                }
                //修改当前软件当前方案
                SystemModel.CurrentScheme = sltProjects.Text;
                //修改配置当前方案
                SchemeHelper.SetCurrentScheme(SystemModel.CurrentScheme);
                //将配置文件替换为当前方案
                ConfigHelper.LoadConfig();
                AntdUI.Message.success(this, $"载入方案{SystemModel.CurrentScheme}成功!", autoClose: 3);
            }
            catch (Exception ex)
            {
                AntdUI.Message.error(this, ex.Message, autoClose: 3);
            }
        }

        private void BtnAddProject_Click(object? sender, EventArgs e)
        {
            try
            {
                var form = new AddSchemeControl(this, "新增方案操作") { Size = new System.Drawing.Size(400, 300) };
                AntdUI.Modal.open(new AntdUI.Modal.Config(this, "", form, TType.None)
                {
                    BtnHeight = 0,
                });
                if (form.submit)
                {
                    string SchemeName = form.SchemeName;
                    //保存到方案配置
                    SchemeHelper.AddScheme(SchemeName);
                    if (form.NullScheme)
                    {
                        //新构建配置文件
                        ConfigHelper.InitializeScheme(SchemeName);
                    }
                    else
                    {
                        //派生当前方案
                        ConfigHelper.DeriveScheme(SchemeName);
                    }
                    //刷新方案列表
                    sltProjects.Items.Clear();
                    List<string> list = SchemeHelper.GetAllSchemes();
                    foreach (string s in list)
                    {
                        sltProjects.Items.Add(s);
                    }
                    string CurrentScheme = SchemeHelper.GetCurrentScheme();
                    sltProjects.SelectedValue = CurrentScheme;
                    AntdUI.Message.success(this, $"新增方案{SchemeName}成功!", autoClose: 3);
                }
            }
            catch (Exception ex)
            {
                AntdUI.Message.error(this, ex.Message, autoClose: 3);
            }
        }

        public List<HikVisionCamera> HKCameras { get; } = new List<HikVisionCamera>();
        public List<Do3ThinkCamera> Cameras { get; } = new List<Do3ThinkCamera>();
        public Dictionary<string, SimboObjectDetection> Dectection { get; } = new Dictionary<string, SimboObjectDetection>();
        public XinJEPLCTcpNet PLC { get; } = XinJEPLCTcpNet.Instance;
        private SLDMotion sLDMotion = new SLDMotion();

        private void MainWindow_Load(object sender, EventArgs e)
        {
        }

        private bool _isClosing = false; // 状态标志

        private void MainWindow_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (_isClosing) return;
            _isClosing = true;
            // 取消默认关闭行为
            e.Cancel = true;

            // 立即隐藏主窗口
            this.Hide();

            // 显示关闭界面
            CloseWindow.Instance.Show();
            Thread.Sleep(200);
            try
            {
                // 执行关闭操作
                foreach (var camera in Cameras)
                {
                    camera.CameraDisConnect();
                }
                foreach (var camera in HKCameras)
                {
                    camera.CameraDisConnect();
                }
                if (PLC != null)
                {
                    PLC.CloseProcess();
                }
                _visionEngine.Stop();//释放模型
                CloseWindow.Instance.Close();// 关闭提示窗口
                                             //Application.Exit();
                System.Environment.Exit(0);
            }
            catch (Exception ex)
            {
                CloseWindow.Instance.Close();

                System.Environment.Exit(0);
            }
        }

        private void segmented1_SelectIndexChanged(object sender, EventArgs e)
        {
            // Get the index of the selected item
            int selectedIndex = segmented1.SelectIndex;

            // Handle each button based on its index
            switch (selectedIndex)
            {
                case 0: // "启动" (Start)
                    HandleStartButton();
                    break;

                case 1: // "停止" (Stop)
                    HandleStopButton();
                    break;

                case 2: // "复位" (Reset)
                    HandleResetButton();
                    break;

                case 3: // "设置" (Settings)
                    HandleLoginButton();
                    break;

                case 4: // "登录" (Login)
                    HandleSettingsButton();
                    break;

                default:
                    break;
            }
            segmented1.SelectIndex = -1;
        }

        public bool CurrentMachine = false;
        public volatile int ProductNum_Total = 0;
        public volatile int ProductNum_OK = 0;
        private readonly object _cameraSummaryLock = new object();
        public SimboVisionDriver? _visionEngine = null;

        public PLCBase? _PLCConfig = null;
        private List<DetectionConfig> DetectionConfigs = new List<DetectionConfig>();
        private List<SimboStationMLEngineSet> SimboStationMLEngineList = new List<SimboStationMLEngineSet>();
        private Dictionary<string, HDevEngineTool> HalconToolDict = new Dictionary<string, HDevEngineTool>();
        public List<RecongnitionLabel> RecongnitionLabelList { get; set; } = new List<RecongnitionLabel>();
        public DateTime ProcessstartTime;

        private void HandleStartButton()
        {
            LogAsync(DateTime.Now, LogLevel.Information, "流程启动中,请稍候...");
            StartProcess();
            LogAsync(DateTime.Now, LogLevel.Action, "流程启动完成!");
        }



        private void StartProcess()
        {
            ProcessstartTime = DateTime.Now;
            lblStartTime.Text = ProcessstartTime.ToString("yyyy-MM-dd HH:mm:ss");
            //计数清零
            PieceCount = 0;


            if (PLC?.Enable == true)
            {
                PLC.OnNewPieces -= MainMotion_NewPieces;
                PLC.OnNewPieces += MainMotion_NewPieces;
            }

            Cameras.ForEach(d =>
            {
                if (d is CameraBase cam)
                {
                    cam.SnapshotCount = 0;
                }
            });

            //PrepareBatchNO();
            // isInPositionChecking = false;
            //isFullTrayChecking = false;
            //队列清空
            // var temp = new List<ITriggerSet>();
            // temp.AddRange(XKRSPLCConfig.TriggerConfigCollection);
            // temp.AddRange(XKRSPLCConfig.SnapshotTriggerConfigCollection);

            //temp.ForEach(t =>
            //{
            //    var diskInfo = XKRSPLCConfig.DiskInfoList.FirstOrDefault(u => u.DiskName == t.DiskName);
            //    if (diskInfo != null)
            //    {
            //        t.AxisNum = diskInfo.DiskAxisNum;
            //    }
            //    else
            //    {
            //        t.AxisNum = -1;
            //    }
            //});

            //if (temp.Any(u => u.AxisNum < 0))
            //{
            //    LogAsync(DateTime.Now, LogLevel.Error, "触发信号归属转盘未确认");
            //    return new ProcessResponse(false);
            //}

            // _diskInfoListInOrder = XKRSPLCConfig.DiskInfoList.OrderBy(u => u.DiskSequence).ToList();
            //  var axisNumList = _diskInfoListInOrder.Select(u => u.DiskAxisNum).ToList();

            /// PrepareMLEngine();

            // if (_PLCConfig?.Enable == true)
            //挡料电机操作
            //  _PLC.FeedingMotor(_PLCConfig.CunToZeroSpeed, _PLCConfig.CunPos, _PLCConfig.CunSpeed, _PLCConfig.CunDirection);

            //流程开启操作配置
            // ProcessInitialAction();
            //  if (_PLC?Enabled == true)
            //皮带
            //   _PLC.Belt(true);

            //DeviceCollection.ForEach(d =>
            //{
            //    if (d is CameraBase c)
            //    {
            //        c.OnHImageOutput -= OnCameraHImageOutput;
            //        c.OnHImageOutput += OnCameraHImageOutput;
            //        c.SnapshotCount = 0;
            //    }
            //});
            _productLists.Clear();

            #region 虚拟相机

            //mOfflineImageTimer = new System.Timers.Timer();

            //mOfflineImageTimer.Elapsed += OnEmitSerialPortAsync;
            //mOfflineImageTimer.Interval = 1000;
            //mOfflineImageTimer.Start();

            #endregion 虚拟相机

            var settings = _visionEngine.DetectionConfigs.Where(u => u.IsEnabled && u.IsAddStation).ToList();
            if (settings != null)
            {
                settings = settings.Where(s => s.IsEnabled).ToList();
                ProductBaseCount = settings.Count;

                for (int i = 0; i < ProductBaseCount * ProductListMulti; i++)
                {
                    ConcurrentDictionary<uint, ProductData> products = new ConcurrentDictionary<uint, ProductData>();
                    _productLists.Add(products);
                }
            }

            //   _MGSCameraList = DeviceCollection
            //.OfType<MGSCameraDriver>()  // 直接筛选出 MGSCameraDriver 类型的元素
            //.Where(camera => camera.IConfig != null && camera.IConfig.IsEnabled)  // 进一步筛选 IConfig 不为 null 且 IsEnabled 为 true
            //.ToList();

            //   ProductBaseCount = _MGSCameraList.Count;


            InitialOEEStatistic();
            //流程执行时PLC
            PLC.StartProcess();




        }


        private uint PieceCount = 0;
        private List<ConcurrentDictionary<uint, ProductData>> _productLists = new List<ConcurrentDictionary<uint, ProductData>>();
        private int ProductListMulti = 1;
        private int ProductBaseCount = 0;

        private int PieceNumberToIndex(uint pn)
        {
            // 物料编号,取余 集合数量

            int ret = (int)(pn % (ProductBaseCount * ProductListMulti));
            return ret;
        }

        private DateTime _ctTime = DateTime.Now;

        public async void MainMotion_NewPieces(int axisIndex, uint pieceNumber)
        {
            //if (MachineState != MachineState.Running && MachineState != MachineState.Warning)
            //{
            //    return;
            //}

            PieceCount++;

            int index = PieceNumberToIndex(pieceNumber);
            // productDatas.Add(pData);
            //转盘2 的物料是不是重新覆盖之前的pDta
            if (axisIndex == 1)
            {
                ProductData pData = new ProductData("", pieceNumber, ProductBaseCount);
                _productLists[index][pieceNumber] = pData;
                LogAsync(DateTime.Now, LogLevel.Action, $">> 轴{axisIndex}新产品{pieceNumber}加入队列{index}----板卡计数{PieceCount}");

            }
           
            DateTime dtNow = DateTime.Now;
            UpdateCT(null, (float)(dtNow - _ctTime).TotalSeconds);
            _ctTime = dtNow;
        }

        public async Task UpdateCT(object objData, float ctTime)
        {
            await Task.Run(() =>
            {
                //OnUpdateCT?.Invoke(objData, ctTime);
            });
        }

        /// <summary>
        /// 相机回调
        /// </summary>
        /// <param name="dt"></param>
        /// <param name="camera"></param>
        /// <param name="imageSet"></param>
        private void OnCameraHImageOutput(DateTime dt, CameraBase camera, Mat imageSet)
        {
            //if (camera.CameraName.Equals("cam1", StringComparison.OrdinalIgnoreCase))
            //{
            //    Console.WriteLine();
            //}
            //if (camera.CameraName.Equals("cam2", StringComparison.OrdinalIgnoreCase))
            //{
            //    Console.WriteLine();
            //}

            // 获取该相机的拍照计数
            uint productNumber = (uint)camera.SnapshotCount;

            Task.Run(async () =>
            {
                using (Mat localImageSet = imageSet.Clone())  // 复制 Mat 避免并发问题
                {
                    // imageSet?.Dispose();
                    // 拍照计数与物件编号一致,查找对应的产品
                    ProductData product = null;
                    //内外壁模组多个相机的处理方法
                    //计算队列的方法不变
                    int index = PieceNumberToIndex(productNumber);
                    // 找到产品存放在哪个队列里
                    ConcurrentDictionary<uint, ProductData> tmpDic = _productLists[index];

                    try
                    {
                        int retryTimes = 100;
                        while (product == null && retryTimes > 0)
                        {
                            if (tmpDic.ContainsKey(productNumber))
                            {
                                product = tmpDic[productNumber];
                            }
                            else
                            {
                                 Thread.Sleep(20);
                                //await Task.Delay(20);
                            }
                            retryTimes--;
                        }
                        // 如果产品为空,则销毁图片,提示错误
                        if (null == product)
                        {
                            List<uint> pnList = tmpDic.Keys.ToList();

                            string pnStr = "";
                            if (pnList != null && pnList.Count > 0)
                            {
                                pnStr = string.Join(",", pnList);
                            }

                            //LogAsync(DateTime.Now, LogLevel.Error, $"{camera.Name} 未找到产品,编号:{productNumber},队列{index}数量:{tmpDic.Count},列表:{pnStr}");
                            localImageSet.Dispose();
                          
                            return;
                        }

                        // LogAsync(DateTime.Now, LogLevel.Information, $"{camera.Name} 找到产品{productNumber},队列{index}数量:{tmpDic.Count}");

                        if (!_cameraRelatedDetectionDict.ContainsKey(camera.CameraName))
                        {
                            localImageSet.Dispose();
                          

                          
                              LogAsync(DateTime.Now, LogLevel.Warning, $"{camera.CameraName} 找到产品{productNumber},但是没有推理1");

                            return;
                        }

                        double totalTime = 0.0;
                        List<ResultState> resultStates = new List<ResultState>();
                        List<string>? detectionDict = _cameraRelatedDetectionDict[camera.CameraName];
                        Stopwatch stopwatch = new Stopwatch();
                        stopwatch.Start();
                        for (int i = 0; i < detectionDict.Count; i++)
                        {
                            string detectionId = detectionDict[i];

                          
                            using (Mat inferenceImage = localImageSet.Clone()) // 仅在此处克隆,确保推理过程中 Mat 有独立副本
                            {
                                DetectStationResult temp1 = _visionEngine.RunInference(inferenceImage, detectionId);

                                resultStates.Add(temp1.ResultState);

                                product.ResultCollection.Add(temp1);
                            }
                        }
                        stopwatch.Stop();
                        if (product.ResultCollection.Count != 0)
                            UpdateResultoverride(dt, camera, resultStates, totalTime, _cameraRelatedDetectionDict.Keys.Count);

                        product.InferenceOne();

                        // LogAsync(DateTime.Now, LogLevel.Information, $"{camera.Name} 推理完成,产品{productNumber}");

                        if (!product.InferenceFinished())
                        {
                            return;
                        }
                        UpdateResultPro(DateTime.Now, null, product.ProductResult.GetEnumDescription());
                   

                        #region 6. 统计产品结果

                        product.ProductResult = product.ResultCollection.Any(u => u.ResultState != ResultState.OK)
                            ? ResultState.B_NG
                            : ResultState.OK;
                        //if (product.ProductResult == ResultState.OK)
                        //{
                        //    PLC.Blowing(productNumber, 1);
                        //}
                        //else
                        //{
                        //    PLC.Blowing(productNumber, 2);
                        //}
                        product.ProductLabelCategory = product.ProductResult.GetEnumDescription();
                        product.ProductLabel = product.ProductResult.GetEnumDescription();

                        #endregion 6. 统计产品结果

                        // 出列
                        ProductData temp = null;

                        int tryTimes = 10;
                        while (temp == null && tryTimes > 0)
                        {
                            if (tmpDic.TryRemove(productNumber, out temp))
                            {
                                break;
                            }

                            tryTimes--;
                            Thread.Sleep(5);
                        }
                        if (temp == null)
                        {
                            string logStr = $"{DateTime.Now}产品{productNumber}出列失败:true," +
                               $"当前队列产品数量:{tmpDic.Count}";
                            this.BeginInvoke(new MethodInvoker(delegate ()
                            {
                               // int currentScrollPosition = richTextBox1.GetPositionFromCharIndex(richTextBox1.TextLength).Y;

                               // richTextBox1.AppendText(logStr);

                                // 设置回原来的滚动位置
                              // richTextBox1.SelectionStart = richTextBox1.TextLength;
                                //richTextBox1.ScrollToCaret();
                            }));
                        }
                        else
                        {
                            try
                            {
                                string logStr = $"{DateTime.Now}产品{productNumber}出列成功:true," +
                              $"产品结果:{temp.ProductResult.GetEnumDescription()}," +
                              $"当前队列产品数量:{tmpDic.Count}";
                                this.BeginInvoke(new MethodInvoker(delegate ()
                                {
                                    //int currentScrollPosition = richTextBox1.GetPositionFromCharIndex(richTextBox1.TextLength).Y;

                                   // richTextBox1.AppendText(logStr);

                                    // 设置回原来的滚动位置
                                   // richTextBox1.SelectionStart = richTextBox1.TextLength;
                                    //richTextBox1.ScrollToCaret();
                                }));
                                //重新生成实例 销毁之前的实例
                                var saveData = temp.GetProductData();
                                using (StreamWriter sw = new StreamWriter("D://123log.txt", true, Encoding.UTF8))
                                {
                                    sw.WriteLine(logStr);
                                }
                            }
                            catch (Exception) { }
                            finally
                            {
                                // temp.Dispose();
                                temp = null;
                            }
                        }

                        // UpdateCT((float)(dtNow - _ctTime).TotalSeconds);
                        //_ctTime = dtNow;
                        // });
                    }
                    catch (Exception ex)
                    {
                        //LogAsync(DateTime.Now, LogLevel.Error, $"流程检测未捕获的异常:{ex.GetExceptionMessage()}");
                        product?.Dispose();
                    }
                }
            });
        }
        public virtual void AddOKProduct(string resultStr)
        {
            if (resultStr.ToLower() == "ok")
            {
                ProductNum_OK++;
            }
        }
        public async Task UpdateResultoverride(DateTime dt, CameraBase objData, List<ResultState> resultStr, double total, int _cameraDictCount)
        {
           // CurrentState = RunState.Running;



            // 根据相机名称找到对应的信息(假设有一个字典或其他集合保存相机相关信息)
            var cameraName = objData?.CameraName; // 假设 CameraBase 有 Name 属性
            if (string.IsNullOrEmpty(cameraName))
            {
                throw new ArgumentException("相机名称不能为空");
            }



            lock (_cameraSummaryLock)
            {
                // 查找或添加相机统计项
                var summary = CameraSummaries.FirstOrDefault(c => c.CameraName == cameraName)
                              ?? new CameraSummary { CameraName = cameraName };

                if (!CameraSummaries.Contains(summary))
                {
                    CameraSummaries.Add(summary);
                }

                if (resultStr.Any(u => u.ToString().ToLower() == "ok"))
                {
                    summary.OKCount++;
                }

                else /*if (resultStr.Equals("TBD", StringComparison.OrdinalIgnoreCase))*/
                {
                    summary.NGCount++;
                }

            }

            await Task.Run(() =>
            {
                OnUpdateCamResult?.Invoke(dt, objData, "");
            });
        }

        public async Task UpdateResultPro(DateTime dt, object objData, string resultStr)
        {
            CurrentState = RunState.Running;

            ProductNum_Total++;
            AddOKProduct(resultStr);



            lock (_productSummaryLock)
            {
                var product = ProductSummaries.FirstOrDefault(u => u.ResultDesc == resultStr);
                if (product != null)
                {
                    product.ProductAmount++;
                }
                else
                {
                    product = new ProductSummary();
                    product.ResultDesc = resultStr;
                    product.ProductAmount = 1;

                    ProductSummaries.Add(product);
                }

                int totalNum = ProductSummaries.Sum(p => p.ProductAmount);
                ProductSummaries.ForEach(p => p.PercentStr = ((double)p.ProductAmount * 100.0 / totalNum).ToString("f2") + " %");
            }

            CalculateOEE();

            await Task.Run(() =>
            {
                OnUpdateResult?.Invoke(dt, objData, resultStr);
            });
            lock (_cameraSummaryLock)
            {
                // 查找或添加相机统计项
                var summary = CameraSummaries.FirstOrDefault(c => c.CameraName == "合计")
                              ?? new CameraSummary { CameraName = "合计" };

                summary.OKCount = ProductNum_OK;
                summary.NGCount = ProductNum_Total - ProductNum_OK;
                if (!CameraSummaries.Contains(summary))
                {
                    CameraSummaries.Add(summary);
                }





            }
            await Task.Run(() =>
            {
                OnUpdateCamResult?.Invoke(dt, objData, "合计");
            });


        }

        private void HandleStopButton()
        {
           // Cameras.Clear();
           // Dectection.Clear();
            // Add the code for the "停止" button click here
            PLC.TurnStart(false);
            CurrentMachine = true;
            //sLDMotion.Stop();
        }

       

        public void CalculateOEE()
        {
            if (TotalTime.TotalHours == 0)
            {
                UPH = 0;
                UPM = 0;
            }
            else
            {
                UPH = (int)(ProductNum_Total / RunTime.TotalHours) + 100;
                UPM = (int)UPH / 60;
            }

            
            //TimeSpan timeSpan = DateTime.Now - ProcessstartTime;

            //UPH = (int)(ProductNum_Total / timeSpan.TotalHours) + 100;
            ////UPM = (int)UPH / 60;
            //this.BeginInvoke(new MethodInvoker(delegate ()
            //{
            //    lblNowtime.Text = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
            //    lblUPH.Text = UPH.ToString();
            //    lblNum.Text = ProductNum_Total.ToString();

            //}));
        }

        private void HandleResetButton()
        {
            // Add the code for the "复位" button click here
            MessageBox.Show("复位按钮按下");
        }

        private void HandleSettingsButton()
        {
            // Add the code for the "设置" button click here

            SettingWindow.Instance.Show();
        }

        private void HandleLoginButton()
        {
            // Add the code for the "登录" button click here
            LoginWindow.Instance.Owner = this;
            LoginWindow.Instance.Show();
        }

        private void splitter1_SplitterMoved(object sender, SplitterEventArgs e)
        {
        }

        private void richTextBox1_TextChanged(object sender, EventArgs e)
        {

        }

        private void splitContainer2_Panel1_Paint(object sender, PaintEventArgs e)
        {

        }
    }
}