using FLY.Thick.Base.Common;
using FLY.Thick.Base.Server;
using FlyADBase;
using Misc;
using System;
using System.ComponentModel;

namespace FLY.Thick.Base.Server
{
    /// <summary>
    /// 使用 TimeGridAdv
    /// 只是来回走的逻辑，不包含数据处理；
    /// 可以设置扫描次数；
    /// 0~posLen；
    /// 可以显示进度；
    /// </summary>
    public class ScanMotion2 : INotifyPropertyChanged
    {
        #region 成员变量

        /// <summary>
        /// 扫描次数， 当为-1时，无限次扫描，>0时，有限次扫描
        /// </summary>
        protected int ScanCnt { get; private set; }

        /// <summary>
        /// 速度
        /// </summary>
        public UInt32 Velocity { get; private set; }

        /// <summary>
        /// 完成
        /// </summary>
        public bool IsFinish { get; private set; }

        public int Progress { get; private set; }

        public event EndEventHandler EndEvent;
        public event PropertyChangedEventHandler PropertyChanged;

        #endregion

        enum CTRLST
        {
            /// <summary>
            /// 
            /// </summary>
            IDLE = 0,
            /// <summary>
            /// 准备动作:归0
            /// </summary>
            READY_ORIGIN = 1,
            /// <summary>
            /// 准备动作:正在归0
            /// </summary>
            READY_ORIGINWAIT = 2,
            /// <summary>
            /// 准备动作:后退到 0 脉冲
            /// </summary>
            READY_BACKW = 3,
            /// <summary>
            /// 准备动作:正在后退
            /// </summary>
            READY_BACKWAIT = 4,
            /// <summary>
            /// 前进到 机架总长
            /// </summary>
            SFORWARD = 5,
            /// <summary>
            /// 前进等待
            /// </summary>
            SFORWAIT_1 = 6,
            /// <summary>
            /// 前进结束，等待获取grid
            /// </summary>
            SFORWAIT_2 = 7,
            /// <summary>
            /// 后退到 0 脉冲
            /// </summary>
            SBACKWARD = 8,
            /// <summary>
            /// 后退等待
            /// </summary>
            SBACKWAIT_1 = 9,
            /// <summary>
            /// 后退结束，等待获取grid
            /// </summary>
            SBACKWAIT_2 = 10,


        }
        CTRLST state;

        private int tempDataCnt = 0;
        public int CurrCnt => tempDataCnt;

        DateTime mStartDataEndTime;
        FlyAD7 flyAd;
        public ScanMotion2()
        {
            state = CTRLST.IDLE;
            IsFinish = false;
        }
        public void Init(FlyAD7 flyAd)
        {
            this.flyAd = flyAd;
            this.flyAd.PositionChangedEvent += FlyAd_PositionChangedEvent;
        }

        private void FlyAd_PositionChangedEvent(object sender, PositionChangedEventArgs e)
        {
            if (state == CTRLST.SFORWAIT_1)
            {
                int p = e.Position * 50 / flyAd.PosLen;

                Progress = (100 * tempDataCnt + p) / ScanCnt;
            }
            else if(state == CTRLST.SBACKWAIT_1)
            {
                int p = (flyAd.PosLen - e.Position) * 50 / flyAd.PosLen;
                Progress = (100 * tempDataCnt + 50 + p) / ScanCnt;
            }
        }

        public void Start(int scanCnt, UInt32 velocity)
        {
            state = CTRLST.READY_ORIGIN;
            IsFinish = false;
            ScanCnt = scanCnt;
            Velocity = velocity;
            tempDataCnt = 0;
            Progress = 0;
        }
        
        /// <summary>
        //返回 false, 还没完成， true 已经完成
        /// </summary>
        /// <returns></returns>
        public bool OnPoll()
        {
            switch (state)
            {
                case CTRLST.IDLE:
                    {
                        return true;
                    }break;
                case CTRLST.READY_ORIGIN:
                    {
                        flyAd.SetVelocity(Velocity);
                        flyAd.Origin();

                        state = CTRLST.READY_ORIGINWAIT;
                    }
                    break;
                case CTRLST.READY_ORIGINWAIT:
                    {
                        if (!flyAd.IsFinish)
                            break;

                        if (flyAd.DriveStatus == DRIVE_MAN_STATUS.STOP_MANUAL)
                            return true;
                        
                        state = CTRLST.READY_BACKW;
                    }
                    break;
                case CTRLST.READY_BACKW:
                    {
                        flyAd.RuntoMin();
                        state = CTRLST.READY_BACKWAIT;
                    }
                    break;
                case CTRLST.READY_BACKWAIT:
                    {
                        if (!flyAd.IsFinish)
                            break;
                        
                        if (flyAd.DriveStatus == DRIVE_MAN_STATUS.STOP_MANUAL)
                            return true;
                        
                        if (flyAd.IsTimeToPushTimeGridAdv)
                            break;
                        
                        state = CTRLST.SFORWARD;
                    }
                    break;
                case CTRLST.SFORWARD:
                    {
                        //记下时间
                        mStartDataEndTime = flyAd.Now;
                        flyAd.RuntoMax();
                        state = CTRLST.SFORWAIT_1;
                    }
                    break;
                case CTRLST.SFORWAIT_1:
                    {
                        if (!flyAd.IsFinish)
                            break;

                        if (flyAd.DriveStatus == DRIVE_MAN_STATUS.STOP_MANUAL)
                            return true;
                        if (flyAd.IsTimeToPushTimeGridAdv)
                            break;

                        FlushAD(DIRECTION.FORWARD);
                        state = CTRLST.SFORWAIT_2;
                        
                    }
                    break;
                case CTRLST.SFORWAIT_2:
                    {
                        state = CTRLST.SBACKWARD;
                    }
                    break;
                case CTRLST.SBACKWARD:
                    {
                        mStartDataEndTime = flyAd.Now;
                        flyAd.RuntoMin();
                        state = CTRLST.SBACKWAIT_1;
                    }
                    break;
                case CTRLST.SBACKWAIT_1:
                    {
                        if (!flyAd.IsFinish)
                            break;
                        if (flyAd.DriveStatus == DRIVE_MAN_STATUS.STOP_MANUAL)
                            return true;
                        if (flyAd.IsTimeToPushTimeGridAdv)
                            break;


                        FlushAD(DIRECTION.BACKWARD);

                        state = CTRLST.SBACKWAIT_2;
                    }
                    break;
                case CTRLST.SBACKWAIT_2:
                    {
                        state = CTRLST.SFORWARD;

                        //扫描次数
                        tempDataCnt++;
                        

                        if (tempDataCnt>=ScanCnt)
                        {
                            //扫描完成
                            state = CTRLST.IDLE;
                            IsFinish = true;
                            return true;
                        }
                    }
                    break;
            }
            return false;
        }
        
        
        private void FlushAD(Misc.DIRECTION direction)
        {
            int start_grid = 0;
            int end_grid = flyAd.PosLen / flyAd.PosOfGrid;
            int gridLen = end_grid - start_grid + 1;
            var timeGridAdv2 = flyAd.GetTimeGridAdv2Event(mStartDataEndTime);
            
            var dat = TimeGridAdvHelperExt.ToGrid(timeGridAdv2.AdList, timeGridAdv2.PosList, flyAd.PosOfGrid, gridLen);

             EndEvent?.Invoke(this, new MiniGridEventArgs()
            {
                grid_start = start_grid,
                direction = direction,
                posOfGrid = flyAd.PosOfGrid,
                buf = dat
            });
            
        }
    }

    
}
