using Model;
using Permission;
using PlcCom;
using Sunny.UI;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Drawing;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Xml.Linq;

namespace PlcUiForm
{
    [FormDescriptionAttribute("窗体基类")]
    public class PlcBaseForm : UIForm
    {
        List<IPlcBindableComponent> PlcBindableComponents = new List<IPlcBindableComponent>();
        private PlcBindingManager _plcBindingManager;
        private PlcContex plcContex;
        static IPlcComProtocol defaultPlcComProtocol;
        public readonly IPlcComProtocol PlcComProtocol;
        private int refreshInterval=100;

        private ControlConfigManager _configManager;

        [Category("PLC")]
        [Description("窗体内PLC寄存的读取周期，单位:ms")]
        public int RefreshInterval
        {
            get { return refreshInterval; }
            set { if (value < 10) value = 10; refreshInterval = value; }
        }

        public static void SetDefaultProtocol(IPlcComProtocol protocol)
        {
            if(protocol == null)
                throw new NullReferenceException(nameof(protocol));
            defaultPlcComProtocol = protocol;
        }
        public PlcBaseForm(IPlcComProtocol protocol)
        {
            InitializeComponent();
            if (protocol != null)
            {
                PlcComProtocol = protocol;
                plcContex = new PlcContex(protocol);
            }
            else
            {
                throw new Exception("请传入正确的通讯协议");
            }
            OtherInitialize();
        }
        public PlcBaseForm()
        {
            InitializeComponent();

            if (defaultPlcComProtocol != null)
            {
                PlcComProtocol = defaultPlcComProtocol;
                plcContex = new PlcContex(defaultPlcComProtocol);
            }
            else
            {
               // throw new Exception("请使用SetDefaultProtocol方法传入正确的通讯协议");
            }
            OtherInitialize();
        }
        private void InitializeComponent()
        {
            this.SuspendLayout();
            // 
            // PlcBaseForm
            // 
            this.ClientSize = new System.Drawing.Size(1221, 640);
            this.Name = "PlcBaseForm";
            this.ZoomScaleRect = new System.Drawing.Rectangle(15, 15, 800, 480);
            this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.PlcComBaseForm_FormClosing);
            this.ResumeLayout(false);

        }

        void OtherInitialize()
        {
            Node.EnableDesignTimeValidation = IsDesignMode;
        }



        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);

            UpdatePermissions();
            // 订阅权限变更事件
            PermissionManager.OnPermissionLevelChanged += OnPermissionChanged;

            //Console.WriteLine(this.GetType().Name);
            //var plcBindableControls = this.Controls.Find("", true).OfType<IPlcUiControl>().ToList();

            var plcBindableControls = FindSpecificControls.FindControlsByInterface<IPlcUiControl>(this);

            PlcBindableComponents.AddRange(plcBindableControls.Select(x => (IPlcBindableComponent)x).ToList());
            PlcBindableComponents.AddRange(GetNonControlComponents());

            foreach (var c in PlcBindableComponents)
            {
                if (c is IPlcInputComponent ic)
                {
                    ic.OnWriteRegisterFailed += OnWriteRegisterFailed;
                    ic.OnUserSettedValue += OnUserSettedValue;
                }

                if (c is IPlcOutputComponent oc)
                {
                    oc.OnReadRegisterFailed += OnReadRegisterFailed;
                    oc.OnUpdateComponentStateFailed += OnUpdateComponentStateFailed;
                }
            }

            _plcBindingManager = new PlcBindingManager();
            _plcBindingManager.ReadOK += BindingManager_ReadOK;
            _plcBindingManager.ReadOneNodeFailed += BindingManager_ComponentReadFailed;
            _plcBindingManager.ReadMultiNodesFailed += BindingManager_ReadMultiNodesFailed;
            _plcBindingManager.ReadOverTime += BindingManager_ReadOverTime;
            _plcBindingManager.Bind(PlcBindableComponents, plcBindableControls);
            if (plcContex != null)
                _plcBindingManager.SetPlcContext(plcContex, RefreshInterval); // 或者根据控件动态判断


            //查找带有最大最小值的控件
            _configManager = new ControlConfigManager(this.GetType().Name);
            foreach (IWithMinMaxValue control in FindSpecificControls.FindControlsByInterface<IWithMinMaxValue>(this))
            {
                control.MinMaxValueChanged += OnMinMaxValueChanged;
                var minMaxValue = _configManager.GetMinMax(Name, ((Control)control).Name);
                control.Minimum = minMaxValue.MinValue;
                control.Maximum = minMaxValue.MaxValue;
            }

            ////查找不是PLC地址绑定，但可以让用户操作的控件
            //foreach (IMyOperationalControl control in FindSpecificControls.FindControlsByInterface<IMyOperationalControl>(this))
            //{
            //    control.OnUserOperatedControl += Control_OnUserOperatedControl;
            //}
        }
        private void UpdatePermissions()
        {
            SetIPermissionControlRequireLevel();
            PermissionManager.ApplyPermissions(this);
        }
        private void SetIPermissionControlRequireLevel()
        {
            if (IsDesignMode)
                return;

            // 从对应权限文件加载授权列表（建议缓存，不要每次都读文件）
            var authorizedControls = PermissionManager.GetAuthorizedControlsForRole(AppSession.CurrentUser.PermissionLevel);

            // 构建查找集
            var authSet = new HashSet<string>(
                authorizedControls.Select(c => $"{c.Namespace}.{c.FormType}.{c.ControlName}")
            );

            // 遍历所有字段
            var fields = this.GetType().GetFields(
                BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public);

            var assembly= this.GetType().Assembly;
            var ns = this.GetType().Namespace;
            var formTypeName = this.GetType().Name;
            foreach (var field in fields)
            {
                var fieldValue = field.GetValue(this);
                if (fieldValue is IActionableControl && fieldValue is IPermissionControl control)
                {
                    if (control.RequiredPermissionLevel != PermissionLevel.无权限)//为无权限的控件不受权限控制
                    {
                        var b = authSet.Contains($"{ns}.{formTypeName}.{((Control)control).Name}");

                        if (b)
                            control.RequiredPermissionLevel = AppSession.CurrentUser.PermissionLevel;
                        else
                            control.RequiredPermissionLevel = PermissionLevel.开发者;
                    }
                }
            }
        }
        //private void Control_OnUserOperatedControl(Control control, object state)
        //{
        //    string opMessage;
        //    if (control is MyUiButton)
        //    {
        //        opMessage = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff") + $" {FormName}->“{control.Text}”按钮被点击";
        //    }
        //    else
        //    {
        //        opMessage = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff") + $" {FormName}->“{control.Name}”被修改为：{state}";
        //    }
        //    AppSession.UserOperations.Add(opMessage);
        //}
        private void OnPermissionChanged(PermissionLevel newPermissionLevel)
        {
            // 在 UI 线程上更新权限（防止跨线程异常）
            if (this.InvokeRequired)
            {
                this.Invoke(new Action(UpdatePermissions));
            }
            else
            {
                UpdatePermissions();
            }
        }

        private IEnumerable<IPlcBindableComponent> GetNonControlComponents()
        {
            var fields = this.GetType().GetFields(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public);
            foreach (var field in fields)
            {
                var value = field.GetValue(this);
                if (value is IPlcBindableComponent component && !(value is Control))
                {
                    yield return component;
                }
            }
        }

        //public static List<string> ReadWriteErrors = new List<string>();
        //public static List<string> UserOperations = new List<string>();

        public event Action ProtocollReadOK;
        private void BindingManager_ReadOK()
        {
            ProtocollReadOK?.Invoke();
        }
        public event Action ProtocollReadOverTime;
        private void BindingManager_ReadOverTime()
        {
            ProtocollReadOverTime?.Invoke();
        }
        private void BindingManager_ReadMultiNodesFailed(List<string> arg1, uint arg2)
        {
           
        }
        private void BindingManager_ComponentReadFailed(IPlcBindableComponent plcBindableComponent, Node node, uint errorCode)
        {
            string err = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff") + $" {FormName}->{GetComponentName(plcBindableComponent)}->{node}，读取失败，错误代码：0X{errorCode:X}";
            AppSession.ReadWriteErrors.Add(err);
        }
        private void OnUpdateComponentStateFailed(IPlcBindableComponent plcBindableComponent,Node node, object state, string errMessage)
        {
            string name = plcBindableComponent is Control control ? control.Name : null;
            string err = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff") + $" {FormName}->{name}，更新状态：\"{state}\"错误，错误信息：{errMessage}";
            AppSession.ReadWriteErrors.Add(err);
        }
        private void OnUserSettedValue(IPlcBindableComponent plcBindableComponent,OperationType operationType, Node node,object oldValue, object newValue)
        {
            var controlName = GetComponentName(plcBindableComponent);

            OperationRecord operationRecord = new OperationRecord
            {
                Timestamp = DateTime.Now,
                OperationType = operationType,
                ControlName = $"{FormName}->{controlName}",
                OldValue= oldValue,
                NewValue = newValue,
                Detail = $"{node}->{newValue.ToString()}",
                User = AppSession.CurrentUser
            };
            OperationRecordService.Log(operationRecord);

            string opMessage = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff") + $" {FormName}->{GetComponentName(plcBindableComponent)}->{node}，人工变更为：{newValue.ToString()}";
            AppSession.UserOperations.Add(opMessage);
        }

        private void OnReadRegisterFailed(IPlcBindableComponent plcBindableComponent, Node node, uint errorCode)
        {
            string err = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff") + $" {FormName}->{GetComponentName(plcBindableComponent)}->{node}，读取失败，错误代码：0X{errorCode:X}";
            AppSession.ReadWriteErrors.Add(err);
        }

        private void OnWriteRegisterFailed(IPlcBindableComponent plcBindableComponent, Node node, uint errorCode)
        {
            string err = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff") + $" {FormName}->{GetComponentName(plcBindableComponent)}->{node}，写入失败，错误代码：0X{errorCode:X}";
            AppSession.ReadWriteErrors.Add(err);
        }
        private void OnMinMaxValueChanged(Control control, double minimum, double maximum)
        {
            _configManager.SetMinMax(this.GetType().Name, control.Name, new MinMaxValue(minimum, maximum));
            _configManager.SaveConfig();
        }


        private void PlcComBaseForm_FormClosing(object sender, FormClosingEventArgs e)
        {
            PermissionManager.OnPermissionLevelChanged -= OnPermissionChanged;
            _plcBindingManager?.Stop();
            FormEx.CloseAllChildForms(this);
        }
        // 窗体关闭时取消订阅，防止内存泄漏
        protected override void OnFormClosed(FormClosedEventArgs e)
        {
            base.OnFormClosed(e);
        }

        public string FormName { 
            get
            {
                if (!string.IsNullOrWhiteSpace(this.Text))
                {
                    return this.Text;
                }
                else if (!string.IsNullOrWhiteSpace(this.Name))
                {
                    return this.Name;
                }
                else
                {
                    return this.GetType().Name;
                }
            }
        }
        public string GetTextOrName(Control control)
        {
            // 使用反射获取控件类型上的 Text 属性
            PropertyInfo textProperty = control.GetType().GetProperty("Text", typeof(string));

            if (textProperty != null)
            {
                // 控件有 Text 属性
                string text = (string)textProperty.GetValue(control);
                if (string.IsNullOrWhiteSpace(text))
                {
                    return control.Name;
                }
                else
                {
                    return text;
                }
            }
            else
            {
                // 控件没有 Text 属性，返回 Name
                return control.Name;
            }
        }
        public string GetComponentName(IPlcBindableComponent plcBindableComponent)
        {
            if (plcBindableComponent is Control control)
            {
                return control.Name;
            }
            else if(plcBindableComponent is IComponent component)
            {
                // 使用反射获取控件类型上的 NodeName 属性
                PropertyInfo NodeNameProperty = component.GetType().GetProperty("NodeName", typeof(string));

                if (NodeNameProperty != null && !string.IsNullOrWhiteSpace((string)NodeNameProperty.GetValue(component))) // 控件有 NodeName 属性，且值不为空
                {
                    return (string)NodeNameProperty.GetValue(component);
                }
                else
                {
                    return component.Site?.Name;
                }
            }
            else
                return string.Empty;
        }
        public string GetNodeNameOrName(IPlcBindableComponent plcBindableComponent)
        {
            if (plcBindableComponent is Control || plcBindableComponent is Component)
            {
                // 使用反射获取控件类型上的 NodeName 属性
                PropertyInfo nodeNameProperty = plcBindableComponent.GetType().GetProperty("NodeName", typeof(string));

                if (nodeNameProperty != null && !string.IsNullOrWhiteSpace((string)nodeNameProperty.GetValue(plcBindableComponent))) // 控件有 NodeName 属性，且值不为空
                {
                    return (string)nodeNameProperty.GetValue(plcBindableComponent);
                }
                else
                {
                    // 控件没有 NodeName 属性，返回 Name
                    if (plcBindableComponent is Control control)
                        return control.Name;
                    else if (plcBindableComponent is IComponent component)
                        return component.Site?.Name;
                    else
                        return string.Empty;
                }
            }
            else
                return string.Empty;
        }
    }
}
