using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.ComponentModel;
using FObjBase;
using Misc;
using System.Collections.ObjectModel;
namespace FlyADBase
{
    public interface IFlyAD : INotifyPropertyChanged
    {
        IPEndPoint LocalEP { get; set; }
        /// <summary>
        /// 从flyad7 获取 的systick 转换的时间
        /// </summary>
        DateTime Now { get; }


        //POS & AD
        int Position { get; }
        int Speed { get; }
        int AD { get; }/*1000ms从AD卡获取(或推送)1个AD值。此AD值只用于调试，定点*/
        int ADMax { get; }//AD值最大值 ，恒定返回65535
        //IO
        UInt16 IStatus { get; }/*input read*/
        UInt16 OStatus { get; }/*output read*/
        /// <summary>
        /// Out0 = 0, SetOutput(0x0001,0x0000);
        /// Out0 = 1, Out1 = 0, SetOutput(0x0003,0x0001);
        /// </summary>
        /// <param name="mask"></param>
        /// <param name="enable"></param>
        void SetOutput(UInt16 mask, UInt16 enable); 

        /// <summary>
        /// 读取参数, 全部！！！！
        /// </summary>
        void UpdateParam();

        #region 配置参数
        void SetSysParam(UInt16 posOfGrid, MOTORTYPE motortype, UInt16 ratio01, UInt16 ratio02);
        MOTORTYPE MotorType { set; get; }
        UInt16 PosOfGrid { set; get; }// 单位 pulse/grid
        UInt16 Ratio01 { get; set; }
        UInt16 Ratio02 { get; set; }

        #endregion

        Int16 PosOffset { set; get; }//脉冲平移
        UInt32 JogVelocity { set; get; }

        #region 速度
        UInt32 Velocity { set; get; }
        UInt32 SVelocity { set; get; }
        UInt32 ATime { set; get; }
        UInt32 DTime { set; get; }
        UInt32 HVelocity1 { set; get; }
        UInt32 HVelocity2 { set; get; }
        void SetPosParam(UInt32 velocity, UInt32 sv, UInt32 atime, UInt32 dtime, UInt32 hspeed1, UInt32 hspeed2);
        #endregion

        #region 密码

        AREA_STATUS AreaStatus { get; }
        AREA_ERR AreaRet { get; }
        /// <summary>
        /// 序列码byte[6]
        /// </summary>
        byte[] Code { get; }
        /// <summary>
        /// 系统剩余时间
        /// </summary>
        int Surplus { get; }
        /// <summary>
        /// 系统授权码access[8]
        /// </summary>
        byte[] Access { get; }
        /// <summary>
        /// 输入系统授权码
        /// </summary>
        /// <param name="access"></param>
        void SetAccess(byte[] access);
        /// <summary>
        /// 初始化系统信息区
        /// </summary>
        void InitArea();

        #endregion


        //grid
        void GetGrid(DIRECTION direction, int grid_start, int grid_len, out int[] dat);
        void GetGrid(DIRECTION direction, out int[] dat);

        event TimeGridEventHandler TimeGridEvent;
        event MiniGridEventHandler MiniGridEvent;
        event IStatusChangedEventHandler IStatusChangedEvent;
        event MiniGridEventHandler GridEvent;



        #region 运行
        void Runto(int to);
        void Origin();
        void Stop();
        void Backward();
        void Forward();
        #endregion

        DRIVE_MAN_ORDER DriveOrder { get; }
        DRIVE_MAN_STATUS DriveStatus { get; }

        #region 同步
        /// <summary>
        /// 同步用标示
        /// </summary>
        Int32 Marker { get; }
        #region 横向脉冲
        /// <summary>
        /// 逻辑横向脉冲偏移  Pos1 + Pos1LCShift = Pos1LC
        /// </summary>
        int Pos1LCShift { get; set; }
        #endregion
        #region 主轴脉冲
        /// <summary>
        /// 纵向脉冲，也叫主轴脉冲
        /// </summary>
        int Position2 { get; set; }
        /// <summary>
        /// 纵向速度
        /// </summary>
        int Speed2 { get; }
        /// <summary>
        /// 纵向偏移,这个是相对量
        /// </summary>
        void SetPos2Offset(int offset);
        /// <summary>
        /// 纵向值补偿系数，补偿时，先乘除后加减
        /// </summary>
        float Pos2Comp { get; set; }
        /// <summary>
        /// 纵向同步事件，0-1事件
        /// </summary>
        /// <param name="pos2"></param>
        /// <param name="immediately">只要是 01，就立刻修正</param>
        void SetPos2At01(int pos2, bool immediately);
     
        #endregion
        #region 同步控制 同步状态转换规则
        /// <summary>
        /// 进入同步状态
        /// </summary>
        /// <param name="pos2"></param>
        void SyncBegin(int pos2);
        /// <summary>
        /// 进入同步状态
        /// </summary>
        void SyncBegin();
        /// <summary>
        /// 退出同步状态
        /// </summary>
        void SyncEnd();
        /// <summary>
        /// 清空同步指令
        /// </summary>
        void SyncClear();
        /// <summary>
        /// 清空POS2同步列表
        /// </summary>
        void SyncPos2Clear();
        #endregion
        #region 同步扫描 脚本指令
        //同步扫描至
        //D+0xE0+开始主轴位置+结束主轴位置+结束横向脉冲位置（逻辑位置）+脉冲开关（1B）+命令识标号（4B）
        void SyncRunAtLC(int pos2_begin, int pos2_end, int pos1lc, bool hasDataGrid, Int32 marker);

        //位于队列头时运行，归零
        //D+0xE1+命令识标号（4B）
        void SyncOrigin(Int32 marker);


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

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


        //等待，ms
        //D+0xE4+毫秒数（4B：int32）+命令识标号（4B）
        void SyncWait(int ms, Int32 marker);

        #endregion
        #endregion
    }

    
    public class IStatusChangedEventArgs : EventArgs
    {
        public IStatusChangedEventArgs(DateTime time, UInt16 istatus, UInt16 ichanged, int pos, int pos2)
        {
            Time = time;
            IStatus = istatus;
            IChanged = ichanged;
            Position = pos;
            Position2 = pos2;
        }

        /// <summary>
        /// 开始时间点
        /// </summary>
        public DateTime Time;
        /// <summary>
        /// 输入口状态
        /// </summary>
        public UInt16 IStatus;
        /// <summary>
        /// 变化量
        /// </summary>
        public UInt16 IChanged;
        /// <summary>
        /// 变化时的脉冲1
        /// </summary>
        public int Position;
        /// <summary>
        /// 变化时的脉冲2
        /// </summary>
        public int Position2;

    }
    public delegate void IStatusChangedEventHandler(object sender, IStatusChangedEventArgs e);


    public class GridAdvUnit
    {
        public DateTime dt;
        public int ad;
        public int pos;
        public UInt16 istatus;
        public override string ToString()
        {
            return $"{dt.Ticks} | {ad} | {pos} | {istatus:X2}";
        }
    }
    public class TimeGridAdvEventArgs : EventArgs
    {
        public TimeGridAdvEventArgs()
        {

        }
        public TimeGridAdvEventArgs(GridAdvUnit[] data)
        {
            Data = data;
        }
        /// <summary>
        /// 数据
        /// </summary>
        public IEnumerable<GridAdvUnit> Data { get; set; }
    }
    public delegate void TimeGridAdvEventHandler(object sender, TimeGridAdvEventArgs e);


    public class TimeGridEventArgs : EventArgs
    {
        public TimeGridEventArgs()
        {

        }
        public TimeGridEventArgs(DateTime time, TimeSpan tspan, int[] data)
        {
            Time = time;
            Ts = tspan;
            Data = data;
        }
        /// <summary>
        /// 数据
        /// </summary>
        public int[] Data { get; set; }
        /// <summary>
        /// 单数据时间间隔
        /// </summary>
        public TimeSpan Ts { get; set; }

        /// <summary>
        /// 开始时间点
        /// </summary>
        public DateTime Time { get; set; }
    }
    public delegate void TimeGridEventHandler(object sender, TimeGridEventArgs e);

    public class MiniGridEventArgs : EventArgs
    {
        public Misc.DIRECTION direction;
        public int posOfGrid;
        public int grid_start;
        public int[] buf;
        public Int32 marker;//扫描标记
    }
    public delegate void MiniGridEventHandler(object sender, MiniGridEventArgs e);

    public delegate void CorrectADsHandler(Misc.DIRECTION direction, int start_grid, int[] dat);


    public enum MOTORTYPE
    {
        NULL = 0,
        VF0 = 1,
        SERVO = 2
    }
    public enum AREA_STATUS
    {
        /// <summary>
        /// 没有读过密码区
        /// </summary>
        NOTLOAD = 0,
        /// <summary>
        /// 读出错
        /// </summary>
        RDERR = 1,
        /// <summary>
        /// 非有效密码区 没有0xAA55 或 0x5A5A 标志
        /// </summary>
        NOTVALID = 2,
        /// <summary>
        /// 写出错
        /// </summary>
        WRERR = 3,
        /// <summary>
        /// 有效密码区
        /// </summary>
        VALID = 4,
        /// <summary>
        /// 有效密码区，应回写EEPROM
        /// </summary>
        VALID_DIRTY = 5,
        /// <summary>
        /// 有效密码区，但回写EEPROM失败
        /// </summary>
        VALID_WRERR = 6
    }

    public enum AREA_ERR
    {
        NO_ERR = 0, // 没有错误
        DUP_ACCESS = 1,//  重复使用码 
        ERR_ACCESS = 2//无效使用码
    }
    public enum DRIVE_MAN_STATUS
    {
        /// <summary>
        /// 正常运行结束
        /// </summary>
        STOP = 0,
        /// <summary>
        /// 正在运行
        /// </summary>
        RUNNING = 1,
        /// <summary>
        /// 指令结束（收到停止指令）
        /// </summary>
        STOP_MANUAL = 2,
        /// <summary>
        /// 运行结束，限位开关闭合
        /// </summary>
        LIMIT = 3
    }
    public enum DRIVE_MAN_ORDER
    {
        IDLE = 'I',
        /// <summary>
        /// 运行到
        /// </summary>
        RUNTO = 'R',
        /// <summary>
        /// 归原点
        /// </summary>
        ORIGIN = 'O',
        /// <summary>
        /// 后退
        /// </summary>
        BACKWORD = 'B',
        /// <summary>
        /// 前进
        /// </summary>
        FORWORD = 'F',
        /// <summary>
        /// 停止
        /// </summary>
        STOP = 'S',
        /// <summary>
        /// 同步
        /// </summary>
        SYNC = 'D',

        /// <summary>
        /// 未知状态
        /// </summary>
        SYNC2 = 'P'
    }


    /// <summary>
    /// 同步状态
    /// </summary>
    public enum SYNC_STATUS
    {
        SYNCST_NO = 0,
        SYNCST_PENDING1 = 1,
        SYNCST_PENDING2 = 2,
        SYNCST_PENDING3 = 3,
        SYNCST_TEMP_OUT = 4,
        SYNCST_WAIT_TO_PENDING = 5,
        SYNCST_RESUME = 6,
        SYNCST_YES = 10,

    }








    public class GridIStatusEventArgs : EventArgs
    {
        public Misc.DIRECTION direction;
        /// <summary>
        /// 输入口 1~12
        /// </summary>
        public int istatus_no;
        public Int32 marker;//扫描标记
        /// <summary>
        /// 扫描开始点
        /// </summary>
        public int pos_start;
        /// <summary>
        /// 扫长度
        /// </summary>
        public int pos_len;
        /// <summary>
        /// 输入口 信号为0, 的范围段
        /// </summary>
        public List<Range> data_0;
        /// <summary>
        /// 输入口 信号为1, 的范围段
        /// </summary>
        public List<Range> data_1;
    }
    public delegate void GridIStatusEventHander(object sender, GridIStatusEventArgs e);

}
