using Advantech.Motion;
using Newtonsoft.Json;
using ProductionControl.Device;
using ProductionControl.Utils;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Xml.Linq;
using static ProductionControl.Device.Axis;
using static ProductionControl.UI.UIAxis;

namespace ProductionControl.UI
{
    public partial class UIAxis : UserControl
    {
        SynchronizationContext SyncContext = null;
        public enum AxisName
        {
            [Description("0-Axis")]
            Axis0 = 0,
            [Description("1-Axis")]
            Axis1 = 1,
            [Description("2-Axis")]
            Axis2 = 2,
            [Description("3-Axis")]
            Axis3 = 3,
        }
        public enum AxisType
        {
            [Description("默认")]
            默认 = 0,
            [Description("直线电机")]
            直线电机 = 1,
        }

         
        public Action<int, string> log;
        //
        private AxisProp axisProp = new AxisProp();
        private Axis axis; 
        public UIAxis()
        {
            InitializeComponent();
            //获取UI线程同步上下文
            SyncContext = SynchronizationContext.Current;
            //init();
        }
        public void init()
        {
            try
            {
                this.propertyGrid1.SelectedObject = axisProp;
                axis = new Axis(); 
                axis.log = log;
                axis.start(); 

                //STATE
                axis.axisStateEvent +=  new System.Action<int, AxisStateType, uint>((axisIndex, type, stateValue) => {
                    if (axisIndex != (int)axisProp.AxisIndex)
                        return;

                    switch (type)
                    {
                        case AxisStateType.AxisState: 
                            if (axisProp.AxState != (AxisState)stateValue)
                            {
                                axisProp.AxState = (AxisState)stateValue;
                                this.refreshUI();
                            }
                            break;
                        case AxisStateType.AxisIOState: 
                            if (axisProp.AxIOStatus != stateValue)
                            {
                                axisProp.AxIOStatus = stateValue;

                                axisProp.ALM = (stateValue & (uint)Ax_Motion_IO.AX_MOTION_IO_ALM) > 0;//需IO close
                                if (axisProp.ALM) log?.Invoke(2, $"Axis{axisIndex} ALM!!!");
                                axisProp.EMG = (stateValue & (uint)Ax_Motion_IO.AX_MOTION_IO_EMG) > 0;//需重置 state
                                if (axisProp.EMG) log?.Invoke(2, $"Axis{axisIndex} EMG!!!");
                                axisProp.LMTP = (stateValue & (uint)Ax_Motion_IO.AX_MOTION_IO_LMTP) > 0;//右极限  true->false
                                axisProp.LMTN = (stateValue & (uint)Ax_Motion_IO.AX_MOTION_IO_LMTN) > 0;//左极限
                                axisProp.ORG = (stateValue & (uint)Ax_Motion_IO.AX_MOTION_IO_ORG) > 0; 
                                axisProp.SVON = (stateValue & (uint)Ax_Motion_IO.AX_MOTION_IO_SVON) > 0;
                                this.refreshUI();

                            } 
                            break;
                        case AxisStateType.AxisMotionState: 
                            if (axisProp.AxMotionState != stateValue)
                            {
                                axisProp.AxMotionState = stateValue;
                                this.refreshUI();
                            }
                            break; 
                    }
                });
                //位置POS
                axis.axisPosEvent += new System.Action<int, AxisPosType, double>((axisIndex, type, pos) => {
                    if (axisIndex != (int)axisProp.AxisIndex)
                        return;

                    switch (type)
                    {
                        case AxisPosType.CmdPos: 
                            if (axisProp.CmdPos != pos)
                            {
                                axisProp.CmdPos = pos;
                                this.refreshUI();
                            }
                            break;
                        case AxisPosType.ActualPos:
                            if (axisProp.ActualPos != pos)
                            {
                                axisProp.ActualPos = pos;
                                this.refreshUI();
                            } 
                            break; 
                    }
                });

                refreshAxisVelParam();
                this.toolStrip1.Enabled = true;
                this.propertyGrid1.Enabled = true; 
            }
            catch (Exception ex)
            {
                this.toolStrip1.Enabled = false;
                this.propertyGrid1.Enabled = false;
                MessageBox.Show(ex.Message, "失败", MessageBoxButtons.OK, MessageBoxIcon.Error);
                this.closeDev();
            }
        }
        private void refreshUI()
        {
            SyncContext.Post(m =>
            {
                var result = m as string;
                propertyGrid1.Refresh();
                tbtnJogOnOff.Text = (axisProp.AxState == AxisState.STA_AX_EXT_JOG) ? "关闭Jog" : "开启Jog";
                tbtnLeft.Enabled = tbtnRight.Enabled = (axisProp.AxState == AxisState.STA_AX_EXT_JOG);
            }, "异步操作完成结果"); 
        }
        private void refreshAxisVelParam()
        {
            var values = axis.getAxisVelParam((int)axisProp.AxisIndex);
            axisProp.VelLow = values[0];
            axisProp.VelHigh = values[1];
            axisProp.Acc = values[2];
            axisProp.Dec = values[3];
            //axisProp.VelLow = values[4];
        }
        private void closeDev()
        {
            try
            {
                if (axis == null) 
                    return; 
                axis.stop();
            }
            catch (Exception ex)
            {
                this.toolStrip1.Enabled = false;
                this.propertyGrid1.Enabled = false;
                MessageBox.Show(ex.Message, "失败", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        protected override void OnHandleDestroyed(EventArgs e) 
        {
            base.OnHandleDestroyed(e);
            // 在此添加需要手动释放资源的代码
            this.closeDev();
        }

        private void tbtnRun_Click(object sender, EventArgs e)
        {
            try
            { 
                axis.setAxisVelParam(axisProp.VelLow, axisProp.VelHigh, axisProp.Acc, axisProp.Dec, (int)axisProp.AxisIndex);
                axis.move_ptp((int)axisProp.AxisIndex, axisProp.Value, axisProp.IsAbsPos);
                //running...
            }
            catch(Exception ex)
            {
                MessageBox.Show(ex.Message, "失败", MessageBoxButtons.OK, MessageBoxIcon.Error);
            } 
        }

        private void tbtnExport_Click(object sender, EventArgs e)
        {
            string filePath = FileUtil.saveAsFile($"Axis{(int)axisProp.AxisIndex}配置.json", "JSON|*.json");
            if (filePath != "")
            {
                string jsonText = axisProp.serialize();
                File.WriteAllText(filePath, jsonText);
                MessageBox.Show("保存成功！", "成功", MessageBoxButtons.OK, MessageBoxIcon.Information);
            }
        }

        private void tbtnImport_Click(object sender, EventArgs e)
        {
            string filePath = FileUtil.openFile("JSON|*.json");
            if (filePath != "")
            {
                string jsonText = File.ReadAllText(filePath);
                 axisProp.deserialize(jsonText);
                this.propertyGrid1.Refresh();
                //this.propertyGrid1.SelectedObject= axisProp;
                //MessageBox.Show("加载成功！", "成功", MessageBoxButtons.OK, MessageBoxIcon.Information);
            }
        }

        private void tbtnHome_Click(object sender, EventArgs e)
        {
            if (axisProp.DeviceType == AxisType.默认)
            {
                axis.home((int)axisProp.AxisIndex);
            }
            else //直线电机 
            { 
                axis.move_ptp((int)axisProp.AxisIndex, - axisProp.ActualPos, false); 
            }
        }

        private void tbtnLeft_MouseDown(object sender, MouseEventArgs e)
        {
            axis.jog((int)axisProp.AxisIndex, 0);
        } 
        private void tbtnLeft_MouseUp(object sender, MouseEventArgs e)
        {
            axis.stopDec();
        }

        private void tbtnRight_MouseDown(object sender, MouseEventArgs e)
        {
            axis.jog((int)axisProp.AxisIndex, 1);
        } 
        private void tbtnRight_MouseUp(object sender, MouseEventArgs e)
        {
            axis.stopDec();
        }

       

        private void tbtnJogOnOff_Click(object sender, EventArgs e)
        {
            if(axisProp.AxState==AxisState.STA_AX_EXT_JOG)
            {
                axis.closeJogMode((int)axisProp.AxisIndex);
                //tbtnJogOnOff.Text = "开启Jog";
            }
            else
            {
                axis.openJogMode((int)axisProp.AxisIndex);
                //tbtnJogOnOff.Text = "关闭Jog";
            }
        }

        private void tbtnStop_Click(object sender, EventArgs e)
        {
            axis.stopDec((int)axisProp.AxisIndex);
        }

        private void tbtnRestState_Click(object sender, EventArgs e)
        {
            axis.resetAxisState((int)axisProp.AxisIndex);
        }

        private void tbtnResetPos_Click(object sender, EventArgs e)
        {
            axis.resetCmdPosition((int)axisProp.AxisIndex);
            axis.resetActualPosition((int)axisProp.AxisIndex);
        }

        private void propertyGrid1_PropertyValueChanged(object s, PropertyValueChangedEventArgs e)
        {
            //其中包含了两个重要的属性：OldValue和ChangeItem。
            //ChangeItem是“PropertyDescriptorGridEntry”类型。一般可以通过ChangeItem.PropertyDescriptor.ComponentType查找到属性的实际类型。 
            //而通过ChangeItem的Label，则可以查看到当前在属性编辑输入框中显示的值。  

            string className = e.ChangedItem.PropertyDescriptor.ComponentType.Name;
            string propertyName = e.ChangedItem.PropertyDescriptor.Name;
            var oldValue = e.OldValue;
            var newValue = e.ChangedItem.Value;
            switch (propertyName)
            {
                case "AxisIndex":
                    refreshAxisVelParam();
                    break;
            }
            
        }
    }
}
