using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using FObjBase;
using System.IO;
using System.ComponentModel;
using System.Xml.Serialization;
using FlyADBase;
using static FLY.Simulation.Flyad7.FLYAD7;
using AutoMapper;
using Newtonsoft.Json;

namespace FLY.Simulation.Flyad7
{
    public class FLYAD7 : IFlyAD, INotifyPropertyChanged
    {
        public IPEndPoint LocalEP
        {
            get
            {
                return Misc.StringConverter.ToIPEndPoint(Addr);
            }
        }
        public string Addr { get; set; } = "127.0.0.1:20008";

        public int Version { get; } = 2;

        /// <summary>
        /// 更新率为 1s 的AD值
        /// </summary>
        public int ADForShow { get; set; }

        /// <summary>
        /// 更新率为 0.1s 的脉冲值
        /// </summary>
        public int PosForShow { get; set; }

        /// <summary>
        /// 更新率为 0.1s 的脉冲值2
        /// </summary>
        public int Pos2ForShow { get; set; }


        private int ADSum;
        private int ADCnt;

        public List<int> TimeGrid = new List<int>();

        public double TimeSpan1ms { get; set; }


        /// <summary>
        /// 原始脉冲值
        /// </summary>
        public int PositionOrg=0;

        #region 模拟部分
        SimDrive mSimDrive = new SimDrive();
        public OrderMan mOrderMan = new OrderMan();

        public enum SIM_MODE 
        {
            /// <summary>
            /// 未知
            /// </summary>
            Unknown,
            /// <summary>
            /// 吹膜
            /// </summary>
            Blowing,
            /// <summary>
            /// 涂布
            /// </summary>
            Coating,
            /// <summary>
            /// 头尾部检测
            /// </summary>
            HeaderAndTailer,
            /// <summary>
            /// 流延
            /// </summary>
            Casting
        }
        /// <summary>
        /// 系统重启时，mSimModeCurr = SimMode ，之后怎么变化都不会影响 mSimModeCurr
        /// </summary>
        public SIM_MODE SimMode { get; set; } = SIM_MODE.Coating;


        /// <summary>
        /// 当前模拟类型
        /// </summary>
        SIM_MODE mSimMode;
        public FLY.Simulation.ISimulationGageAD mSimGageAD;
        //public SimDrive_VF0 mSimDriveVF0 = new SimDrive_VF0();
        //public SimDrive_Servo mSimDriveServo = new SimDrive_Servo();
        #endregion


        public FLYAD7()
        {
            if (!Load())
                Save();
        }
        public FLYAD7(string filePath) {
            file_path = filePath;
            if (!Load())
                Save();
        }

        public void Init(FLY.Simulation.ISimulationGageAD simulationGageAD) {
            mSimGageAD = simulationGageAD;
            Init2();
        }
        public void Init() {

            mSimMode = SimMode;

            switch (mSimMode)
            {
                case SIM_MODE.Blowing:
                    mSimGageAD = new FLY.Simulation.Blowing.GageAD();
                    break;
                case SIM_MODE.HeaderAndTailer:
                    mSimGageAD = new FLY.Simulation.HeaderAndTailer.GageAD();
                    break;
                case SIM_MODE.Casting:
                    mSimGageAD = new FLY.Simulation.Casting.GageAD();
                    break;
                case SIM_MODE.Coating:
                    mSimGageAD = new FLY.Simulation.Coating.GageAD();
                    break;
                default:
                    throw new Exception("不支持 SIM_MODE" + mSimGageAD.ToString());
            }

            Init2();
        }

        void Init2() {
            HVelocity1 = 3000;
            HVelocity2 = 100;
            Velocity = 3000;
            SVelocity = 50;
            JogVelocity = 3000;
            ATime = 500;
            DTime = 500;

            mSimDrive.MotorType = MotorType;
            mSimDrive.MaxPos = (int)(mSimGageAD.TotalLength / mSimGageAD.Mmpp);
            mSimDrive.MinPos = 0;
            mSimDrive.OrgPos = (int)(50 / mSimGageAD.Mmpp);

            mSimDrive.AccTime = ATime;
            mSimDrive.DecTime = DTime;
            mSimDrive.SVelocity = SVelocity / Ratio;
            mSimDrive.PosOffset = PosOffset;

            mOrderMan.Init(this, mSimDrive);
            mOrderMan.order_org.Velocity1 = HVelocity1 / Ratio;
            mOrderMan.order_org.Velocity2 = HVelocity2 / Ratio;
            mOrderMan.order_runto.Velocity = Velocity / Ratio;
            mOrderMan.order_forw.Velocity = JogVelocity / Ratio;
            mOrderMan.order_backw.Velocity = JogVelocity / Ratio;

            mOrderMan.order_sync.mSyncOrderList = mSyncOrderList;
            mOrderMan.FinishEvent += new OrderMan.FinishEventHandler(mSimDriveMan_FinishEvent);

            this.PropertyChanged += new PropertyChangedEventHandler(FLYAD7_PropertyChanged);

            PollModule.Current.Poll_Config(
                PollModule.POLL_CONFIG.ADD,
                new PollModule.PollHandler(OnPoll),
                new TimeSpan((long)(TimeSpan.TicksPerMillisecond * 1.28)));
            //一定只能用TimeSpan.FromTicks(12800)
            //TimeSpan.FromMilliseconds(1.28) 会被取整，最后是 1ms
        }
        
        
        void mSimDriveMan_FinishEvent(bool isNormalStop)
        {
            if (isNormalStop)
                DriveStatus = DRIVE_MAN_STATUS.STOP;
            else
                DriveStatus = DRIVE_MAN_STATUS.LIMIT;

            DriveOrder = DRIVE_MAN_ORDER.IDLE;
        }

        void FLYAD7_PropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            if (e.PropertyName == nameof(DriveOrder))
            {
                switch (DriveOrder) 
                {

                    case DRIVE_MAN_ORDER.FORWORD:
                        DriveStatus = DRIVE_MAN_STATUS.RUNNING;
                        mOrderMan.Forw();
                        break;
                    case DRIVE_MAN_ORDER.BACKWORD:
                        DriveStatus = DRIVE_MAN_STATUS.RUNNING;
                        mOrderMan.Backw();
                        break;
                    case DRIVE_MAN_ORDER.ORIGIN:
                        DriveStatus = DRIVE_MAN_STATUS.RUNNING;
                        mOrderMan.Org();
                        break;
                    case DRIVE_MAN_ORDER.RUNTO:
                        DriveStatus = DRIVE_MAN_STATUS.RUNNING;
                        mOrderMan.Runto(DriveRuntoTarget);
                        break;
                    case DRIVE_MAN_ORDER.SYNC:
                        DriveStatus = DRIVE_MAN_STATUS.RUNNING;
                        mOrderMan.Sync();
                        break;
                    case DRIVE_MAN_ORDER.STOP:
                        DriveStatus = DRIVE_MAN_STATUS.RUNNING;
                        mOrderMan.Stop();
                        break;
                    case DRIVE_MAN_ORDER.IDLE:
                        DriveStatus = DRIVE_MAN_STATUS.STOP;
                        break;
                }
            }

            else if(e.PropertyName == nameof(PosOffset))
            {
                mSimDrive.PosOffset = PosOffset;
            }
            else if (e.PropertyName == nameof(MotorType))
            {
                mSimDrive.MotorType = MotorType;
            }
            else if (e.PropertyName == nameof(Ratio))
            {

                mOrderMan.order_org.Velocity1 = HVelocity1 / Ratio;
                mOrderMan.order_org.Velocity2 = HVelocity2 / Ratio;
                mOrderMan.order_runto.Velocity = Velocity / Ratio;
                mOrderMan.order_forw.Velocity = JogVelocity / Ratio;
                mOrderMan.order_backw.Velocity = JogVelocity / Ratio;
                mSimDrive.SVelocity = SVelocity / Ratio;

            }
            else if (e.PropertyName == nameof(JogVelocity))
            {
                mOrderMan.order_forw.Velocity = JogVelocity / Ratio;
                mOrderMan.order_backw.Velocity = JogVelocity / Ratio;
            }

            else if (e.PropertyName == nameof(Velocity))
            {
                mOrderMan.order_runto.Velocity = Velocity / Ratio;
            }
            else if (e.PropertyName == nameof(SVelocity))
            {
                mSimDrive.SVelocity = SVelocity / Ratio;
            }
            else if (e.PropertyName == nameof(HVelocity1))
            {
                mOrderMan.order_org.Velocity1 = HVelocity1 / Ratio;
            }
            else if (e.PropertyName == nameof(HVelocity2))
            {
                mOrderMan.order_org.Velocity2 = HVelocity2 / Ratio;
            }
            else if (e.PropertyName == nameof(DTime))
            {
                mSimDrive.DecTime = DTime;
            }
            else if (e.PropertyName == nameof(ATime))
            {
                mSimDrive.AccTime = ATime;
            }
        }


        class SimulationDataCell
        {
            public UInt16 istatus;
            public UInt32 ad;
            public override string ToString()
            {
                return "ad=" + ad.ToString() + " istatus=" + istatus.ToString("X3");
            }
        }


        string file_path = "simulation_flyad7.json";
        public bool Save() 
        {
            return FlyAd7JsonDb.Save(this, file_path);
        }

        
        public bool Load() 
        {
            return FlyAd7JsonDb.Load(this, file_path);
        }







        double systick;
        public Int32 GetSysTick()
        {
            //以读到的 mSimulationDatas_idx 作为时间， 一个为1.28ms
            return (Int32)systick;
        }
        public Int32 GetSysTick(DateTime dt) 
        {
            return (Int32)(systick + (dt - Now).TotalMilliseconds);
        }
        


        //1.28ms 触发一次
        void OnPoll() 
        {
            if (Now == DateTime.MinValue)
            {
                Now = DateTime.Now;
                systick = 0;
            }
            else
            {
                Now += TimeSpan.FromTicks((int)(TimeSpan.TicksPerMillisecond * 1.28));
                systick += 1.28;
            }

            UpdateAD();
            UpdatePos();
            UpdateIO();
            UpdateDrive();
        }

        DateTime dt = DateTime.MinValue;
        void UpdateTimeSpan1ms()
        {
            DateTime d = DateTime.Now;
            if (dt == DateTime.MinValue)
                dt = d;
            else
            {
                TimeSpan1ms = (d-dt).TotalMilliseconds;
                dt = d;
            }
        }

        Random random = new Random();
        void UpdateAD() 
        {
            mSimGageAD.OnPoll(Now);

            int mm = (int)(mSimGageAD.Mmpp * mSimDrive.PhysicalPos);
            int ad = mSimGageAD.GetAD(mm);
            //添加随机数
            double p = random.NextDouble();
            ad = (int)(ad * (1 + (p - 0.5) * 0.001));
            if (ad < 0)
                ad = 0;
            else if (ad > 65535)
                ad = 65535;


            ADSum += ad;
            ADCnt++;
            AD = ad;
            TimeGrid.Add(ad);
            if (TimeGrid.Count >= 200)
            {
                ADForShow = ADSum / ADCnt;
                ADSum = 0;
                ADCnt = 0;

                UpdateTimeSpan1ms();
                if (TimeGridEvent != null) 
                {
                    TimeGridEvent.Invoke(this,
                        new TimeGridEventArgs(
                            Now,
                            TimeSpan.FromMilliseconds(1.28),
                            TimeGrid.ToArray()));
                }
                TimeGrid.Clear();
            }
        }

        public class PosGrid 
        {
            
            public int[] Datas = new int[1000];
            List<int> gridsum = new List<int>();
            int grid_index_last = -1;//上一个grid_index
            bool isEnable;
            int grid_start = 0;
            public void Start() 
            {
                isEnable = true;
                grid_start = grid_index_last;
            }
            public void End() 
            {
                if (isEnable)
                {
                    if (gridsum.Count > 0)
                    {
                        Datas[grid_index_last] = (int)(gridsum.Average());
                        gridsum.Clear();
                    }
                    int grid_end = grid_index_last;
                    Misc.DIRECTION dir = Misc.DIRECTION.FORWARD;

                    if (grid_end < grid_start)
                    {
                        int t = grid_start;
                        grid_start = grid_end;
                        grid_end = t;
                        dir = Misc.DIRECTION.BACKWARD;
                    }
                    int len = grid_end - grid_start + 1;
                    int[] data = Datas.Skip(grid_start).Take(len).ToArray();
                    if (PushEvent != null)
                        PushEvent(false, dir, grid_start, data);
                } isEnable = false;
                
            }
            public delegate void PushEventHandler(bool isMini, Misc.DIRECTION dir, int grid_start, int[] data);
            public event PushEventHandler PushEvent;

            public void UpdateGrid(int grid_index, int ad) 
            {
                if (grid_index >= 0 && grid_index < Datas.Count())
                {
                    if (grid_index_last == grid_index)
                    {
                        gridsum.Add(ad);
                    }
                    else
                    {
                        Misc.DIRECTION dir = Misc.DIRECTION.FORWARD;
                        if (grid_index < grid_index_last)
                            dir = Misc.DIRECTION.BACKWARD;
                        if (gridsum.Count > 0)
                        {
                            Datas[grid_index_last] = (int)(gridsum.Average());
                            gridsum.Clear();
                            //TODO 推送MINIGRID
                            if (isEnable) 
                            {
                                int[] data = new int[1];
                                data[0] = Datas[grid_index_last];
                                if (PushEvent != null)
                                    PushEvent(true, dir, grid_index_last, data);
                            }
                        }
                        grid_index_last = grid_index;
                    }
                }
            }    
        }
        public PosGrid mPosGrid = new PosGrid();
        
        void UpdatePos() 
        {
            Position = mSimDrive.CurrPos;
            //Speed = mSimDrive.Speed;    
            mPosGrid.UpdateGrid(Position / PosOfGrid, AD);


            Position2Org = mSimGageAD.GetPosition2();

            //同步模式
            if (mSyncPos2List.Position2Changed(Position2, out int pos2))
            {
                Position2 = pos2;
            }

            Speed2 = mSimGageAD.GetSpeed2();
        }


       
        void UpdateIO() 
        {
            mSimGageAD.SetOutput(OStatus);

            UInt16 istatus = mSimGageAD.GetInput();

            if (mSimDrive.IsMaxLimit)
                Misc.MyBase.SIGNBIT(ref istatus, IODefinition.IN_MAXLIMIT);
            else
                Misc.MyBase.CLEARBIT(ref istatus, IODefinition.IN_MAXLIMIT);
            if (mSimDrive.IsMinLimit)
                Misc.MyBase.SIGNBIT(ref istatus, IODefinition.IN_MINLIMIT);
            else
                Misc.MyBase.CLEARBIT(ref istatus, IODefinition.IN_MINLIMIT);

            if (mSimDrive.IsOrg)
                Misc.MyBase.CLEARBIT(ref istatus, IODefinition.IN_ORG);
            else
                Misc.MyBase.SIGNBIT(ref istatus, IODefinition.IN_ORG);

            //同步模式下才有这个
            UInt16 inchange = (UInt16)(istatus ^ IStatus);
            if (Misc.MyBase.CHECKBIT(inchange, IODefinition.IN_VSENSOR))
            {
                //处理position2
                if (mSyncPos2List.VSensorChanged(Misc.MyBase.CHECKBIT(istatus, IODefinition.IN_VSENSOR), Position2, out int pos2))
                {
                    Position2 = pos2;
                }
            }
            IStatus = istatus;



        }
        class SyncPos2Collection
        {
            List<SyncPos2Item> list = new List<SyncPos2Item>();
            int curr_offset = int.MaxValue;
            public void Add(SyncPos2Item item) 
            {
                list.Add(item);
            }
            public void Clear() 
            {
                list.Clear();
            }
            /// <summary>
            /// 信号改变时调用
            /// </summary>
            /// <param name="vsensor"></param>
            /// <param name="position2"></param>
            public bool VSensorChanged(bool vsensor, int position2, out int correct_pos2) 
            {
                correct_pos2 = position2;
                if (list.Count() == 0)
                    return false;//列表是空的，什么都不干

                SyncPos2Item spitem = list.First();//当前在处理的项

                if (vsensor == spitem.At01) 
                {
                    int offset = position2 - spitem.pos2;
                    if (Math.Abs(curr_offset) > Math.Abs(offset))
                    {
                        curr_offset = offset;
                        return false;
                    }
                    else
                    {
                        //已经找到最近的一个
                        correct_pos2 = spitem.pos2 + curr_offset;
                        curr_offset = int.MaxValue;
                        list.RemoveAt(0);

                        if (list.Count() > 0)
                        {
                            spitem = list.First();//当前在处理的项
                            if (vsensor == spitem.At01)
                                curr_offset = position2 - spitem.pos2;
                        }
                        return true;
                    }
                }
                return false;
            }
            /// <summary>
            /// 脉冲改变时调用
            /// </summary>
            /// <param name="position2"></param>
            /// <param name="correct_pos2"></param>
            /// <returns></returns>
            public bool Position2Changed(int position2, out int correct_pos2) 
            {
                correct_pos2 = position2;
                if (list.Count() == 0)
                    return false;//列表是空的，什么都不干

                SyncPos2Item spitem = list.First();//当前在处理的项

                if(curr_offset!=int.MaxValue)//之前有一个信号
                {
                    int offset = position2 - spitem.pos2;
                    if (Math.Abs(curr_offset) > Math.Abs(offset))
                    {
                        return false;
                    }
                    else
                    {
                        //已经找到最近的一个
                        correct_pos2 = spitem.pos2 + curr_offset;
                        curr_offset = int.MaxValue;
                        list.RemoveAt(0);
                        return true;
                    }
                }
                return false;
            }

        }

        void UpdateDrive() 
        {
            mSimDrive.OnPoll(Now);
            mOrderMan.OnPoll();
        }

        

        #region INotifyPropertyChanged 成员
        protected void NotifyPropertyChanged(string propertyName)
        {
            if (this.PropertyChanged != null)
                this.PropertyChanged.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
        public event PropertyChangedEventHandler PropertyChanged;

        #endregion


        #region IFlyAD接口

        /// <summary>
        /// systick 转换的时间
        /// </summary>
        public DateTime Now { get; set; } = DateTime.MinValue;



        public int Position { get; set; }


        public int Speed { get; set; }


        public int AD { get; set; }

        public int ADMax
        {
            get { return 0xffff; }
        }


        public UInt16 IStatus { get; set; }


        public UInt16 OStatus { get; set; } = 0xf;


        public void SetOutput(ushort mask, ushort enable)
        {
            UInt16 ostatus = OStatus;
            for (int i = 0; i < 16; i++)
            {
                if (Misc.MyBase.CHECKBIT(mask, i))
                {
                    if (Misc.MyBase.CHECKBIT(enable, i))
                        Misc.MyBase.SIGNBIT(ref ostatus, i);
                    else
                        Misc.MyBase.CLEARBIT(ref ostatus, i);
                }
            }
            OStatus = ostatus;
        }

        public void UpdateParam()
        {
            //throw new NotImplementedException();
        }
        #region 配置参数
        public void SetSysParam(ushort posOfGrid, FlyADBase.MOTORTYPE motortype, ushort ratio01, ushort ratio02)
        {
            //不需要实现
        }

        
        public MOTORTYPE MotorType { get; set; } = MOTORTYPE.VF0;


        //1个Grid=?脉冲数(2B)
        public UInt16 PosOfGrid { get; set; } = 10;



        public double Ratio => 1.0 * Ratio01 / Ratio02;
        /// <summary>
        /// //电机比例(2B)
        /// </summary>
        public UInt16 Ratio01 { get; set; } = 1;

        /// <summary>
        /// 脉冲比例(2B)
        /// </summary>
        public UInt16 Ratio02 { get; set; } = 1;

        #endregion


        public Int16 PosOffset { get; set; }


        public UInt32 JogVelocity { get; set; } = 500;

        #region 速度

        public UInt32 Velocity { get; set; }

        public uint SVelocity { get; set; }

        UInt32 atime;
        public UInt32 ATime { get; set; }

        public UInt32 DTime { get; set; }



        public UInt32 HVelocity1 { get; set; }



        public UInt32 HVelocity2 { get; set; }

        public void SetPosParam(uint velocity, uint sv, uint atime, uint dtime, uint hspeed1, uint hspeed2)
        {

        }


        #endregion

        #region 密码

        public AREA_STATUS AreaStatus { get; set; }

        public AREA_ERR AreaRet { get; set; }




        public byte[] Code { get; } = new byte[7] { 0x74, 0xB7, 0x07, 0x4E, 0x52, 0x3D, 0x06 };

        public int Surplus { get; set; } = 8000;

        public byte[] Access { get; } = new byte[8] { 0x19, 0x4A, 0xA5, 0x21, 0x7B, 0x74, 0x1A, 0x00 };

        public void SetAccess(byte[] access)
        {
            if (access.Length != 8)
                return;
            Array.Copy(access, Access, 8);
            AreaStatus = AREA_STATUS.VALID; 
            AreaRet = AREA_ERR.NO_ERR;
            Surplus = 8000;
        }

        public void InitArea()
        {
            throw new NotImplementedException();
        }
        #endregion



        public void GetGrid(Misc.DIRECTION direction, int grid_start, int grid_len, out int[] dat) 
        {
            dat = null;
        }
        public void GetGrid(Misc.DIRECTION direction, out int[] dat) 
        {
            GetGrid(direction, 0, 1000,out  dat);
        }

        public event TimeGridEventHandler TimeGridEvent;

        public event MiniGridEventHandler MiniGridEvent;

        public event MiniGridEventHandler GridEvent;

        public event IStatusChangedEventHandler IStatusChangedEvent;
        public event DriveStatusChangedEventHandler DriveStatusChangedEvent;
        public event PositionChangedEventHandler PositionChangedEvent;
        public event PositionChangedEventHandler Position2ChangedEvent;

        public void Runto(int to)
        {
            Drive(DRIVE_MAN_ORDER.RUNTO, to);
        }

        public void Origin()
        {
            Drive(DRIVE_MAN_ORDER.ORIGIN);
        }

        public void Stop()
        {
            Drive(DRIVE_MAN_ORDER.STOP);
        }

        public void Backward()
        {
            Drive(DRIVE_MAN_ORDER.BACKWORD);
        }

        public void Forward()
        {
            Drive(DRIVE_MAN_ORDER.FORWORD);
        }


        public DRIVE_MAN_ORDER DriveOrder { get; set; }


        public DRIVE_MAN_STATUS DriveStatus { get; set; }


        int DriveRuntoTarget;

        void Drive(DRIVE_MAN_ORDER order, object param) 
        {
            if (order == DRIVE_MAN_ORDER.RUNTO)
            {
                DriveRuntoTarget = (int)param; 
            }
            DriveOrder = order;
        }
        void Drive(DRIVE_MAN_ORDER order) 
        {
            Drive(order, null);
        }
        #endregion

        #region 同步

        /// <summary>
        /// 同步用标示
        /// </summary>
        public Int32 Marker { get; set; }

        #region 横向脉冲

        /// <summary>
        /// 逻辑横向脉冲偏移  Pos1 + Pos1LCShift = Pos1LC
        /// </summary>
        public int Pos1LCShift { get; set; } 

        public void SetPos1LCShift(int value)
        {
            Pos1LCShift = value;
        }
        #endregion
        #region 主轴脉冲
        private int position2_org;
        int Position2Org 
        {
            get { return position2_org; }
            set {
                if (position2_org != value) 
                {
                    position2_org = value;
                    
                    cal_position2();
                }
            }
        }
        private int position2;
        /// <summary>
        /// 纵向脉冲，也叫主轴脉冲
        /// </summary>
        public int Position2 {
            get { return position2; }
            set {
                if (position2 != value) 
                {
                    position2 = value;

                    Pos2Shift = position2 - Position2Org;
                }
            }
        }

        void cal_position2() 
        {
            position2 = Position2Org + Pos2Shift;
        }

        public int Speed2 { get; set; }

        int pos2shift=0;
        /// <summary>
        /// 纵向偏移
        /// </summary>
        int Pos2Shift
        {
            get {
                return pos2shift;
            }

            set {
                if (pos2shift != value) 
                {
                    pos2shift = value;
                    cal_position2();
                }
            }
        }
        public void SetPos2Offset(int offest) 
        {
            Pos2Shift += offest;
        }

        public int HardwareVersion { get; set; } = 2;

        struct SyncPos2Item
        {
            public bool At01;//? or At10
            public int pos2;
            public bool immediately;
        }
        SyncPos2Collection mSyncPos2List = new SyncPos2Collection();
        
        /// <summary>
        /// 纵向同步事件，0-1事件
        /// </summary>
        /// <param name="pos2"></param>
        public void SetPos2At01(int pos2,bool immediately) 
        {
            mSyncPos2List.Add(new SyncPos2Item() { At01 = true, pos2 = pos2, immediately = immediately });
        }

        #endregion
        #region 同步控制 同步状态转换规则
        /// <summary>
        /// 进入同步状态
        /// </summary>
        /// <param name="pos2"></param>
        public void SyncBegin(int pos2) 
        {
            SetPos2(pos2);
            SyncBegin();
        }
        /// <summary>
        /// 进入同步状态
        /// </summary>
        public void SyncBegin() 
        {
            Drive(DRIVE_MAN_ORDER.SYNC);
        }
        /// <summary>
        /// 退出同步状态
        /// </summary>
        public void SyncEnd() 
        {
            Drive(DRIVE_MAN_ORDER.STOP);
        }

        /// <summary>
        /// 清空同步指令
        /// </summary>
        public void SyncClear()
        {
            mSyncOrderList.Clear();
        }
        /// <summary>
        /// 清空POS2同步列表
        /// </summary>
        public void SyncPos2Clear()
        {
            mSyncPos2List.Clear();
        }
        public UInt16 GetSyncOrderCnt()
        {
            return (UInt16)mSyncOrderList.Count();
        }
        public SYNC_STATUS GetSyncStatus()
        {
            if (DriveOrder == DRIVE_MAN_ORDER.SYNC)
                return SYNC_STATUS.SYNCST_YES;
            else
                return SYNC_STATUS.SYNCST_NO;
        }
        #endregion
        #region 同步扫描 脚本指令



        List<ASyncOrder> mSyncOrderList = new List<ASyncOrder>();




        //同步扫描至
        //D+0xE0+开始主轴位置+结束主轴位置+结束横向脉冲位置（逻辑位置）+脉冲开关（1B）+命令识标号（4B）
        public void SyncRunAtLC(int pos2_begin, int pos2_end, int pos1lc, bool hasDataGrid, Int32 marker) 
        {
            mSyncOrderList.Add(
                new SyncOrder_RunAtLC()
                {
                    pos2_begin = pos2_begin,
                    pos2_end = pos2_end,
                    pos1lc_end = pos1lc,
                    hasDataGrid = hasDataGrid,
                    marker = marker
                });
        }

        //7.2	位于队列头时运行，归零
        //D+0xE1+命令识标号（4B）
        public void SyncOrigin(Int32 marker) 
        {
            mSyncOrderList.Add(
                new SyncOrder_Origin()
                {
                    marker = marker
                });
        }


        //7.3	位于队列头时运行，以速度运行至物理位置
        //D+0xE2+横向脉冲位置（4B：int32，物理位置）+速度（4B：int32）+脉冲开关（1B）+命令识标号（4B）
        public void SyncRunTo(int pos1, UInt32 velocity, bool hasDataGrid, Int32 marker)
        {
            mSyncOrderList.Add(
                new SyncOrder_RunTo()
                {
                    pos1 = pos1,
                    velocity = velocity,
                    hasDataGrid = hasDataGrid,
                    marker = marker
                });
        }

        //7.3	位于队列头时运行，以速度运行至逻辑位置
        //D+0xE3+横向脉冲位置（4B：int32，逻辑位置）+速度（4B：int32）+脉冲开关（1B）+命令识标号（4B）
        public void SyncRunToLC(int pos1lc, UInt32 velocity, bool hasDataGrid, Int32 marker)
        {
            mSyncOrderList.Add(
                new SyncOrder_RunToLC()
                {
                    pos1lc = pos1lc,
                    velocity = velocity,
                    hasDataGrid = hasDataGrid,
                    marker = marker
                });
        }


        //7.4	等待，ms
        //D+0xE4+毫秒数（4B：int32）+命令识标号（4B）
        public void SyncWait(int ms, Int32 marker)
        {
            mSyncOrderList.Add(
                new SyncOrder_Wait()
                {
                    ms = ms,
                    marker = marker
                });
        }


        #endregion
        #endregion

        public void SetVelocity(uint velocity)
        {
            Velocity = velocity;
        }

        public void SetPos2(int postion2)
        {
            Position2 = postion2;
        }
    }
    public class FlyAd7JsonDb 
    {
        static Mapper Mapper { get; } = new AutoMapper.Mapper(new MapperConfiguration(c =>
        {
            c.CreateMap<FLYAD7, FlyAd7JsonDb>().ForMember(d => d.Addr, opt =>
            {
                opt.MapFrom(s=>s.LocalEP.ToString());
            }).ReverseMap().ForMember(d => d.LocalEP, opt =>
            {
                opt.MapFrom(s => Misc.StringConverter.ToIPEndPoint(s.Addr));
            });
        }));

        public static bool Save(FLYAD7 src, string filePath)
        {

            var p = Mapper.Map<FlyAd7JsonDb>(src);
            try
            {
                File.WriteAllText(filePath, JsonConvert.SerializeObject(p, Formatting.Indented));
            }
            catch
            {
                //异常，没有json 编码失败
                return false;
            }
            return true;
        }


        public static bool Load(FLYAD7 src, string filePath)
        {
            try
            {
                if (File.Exists(filePath))
                {
                    string json = File.ReadAllText(filePath);
                    var p = JsonConvert.DeserializeObject<FlyAd7JsonDb>(json);
                    Mapper.Map(p, src);
                    return true;
                }
            }
            catch
            {
                //异常，没有json 解码失败
                return false;
            }
            return false;
        }

        public string Addr;
        public SIM_MODE SimMode;
        public MOTORTYPE MotorType;
        public UInt16 PosOfGrid;

        /// <summary>
        /// //电机比例(2B)
        /// </summary>
        public UInt16 Ratio01;

        /// <summary>
        /// 脉冲比例(2B)
        /// </summary>
        public UInt16 Ratio02;
        public UInt32 JogVelocity;
        public Int16 PosOffset;



    }
    public static class FLYAD7_IODefinition
    {
        public const int IN_ORG = 2;
        public const int IN_MINLIMIT = 3;
        public const int IN_MAXLIMIT = 4;
        public const int IN_FORW = 7;
        public const int IN_BACKW = 8;
        public const int IN_VSENSOR = 12;
    }
}
