using FLY.Thick.Base.Common;
using FLY.Thick.Base.IService;
using FLY.Thick.Base.Server;
using FLY.Thick.FilmCasting.Common;
using FLY.Thick.FilmCasting.Server;
using FLY.Thick.FilmCasting.Server.Model;
using FLY.Thick.RemoteHistory;
using FlyADBase;
using FObjBase;

using Misc;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Threading;
using FlyADIODefine = FLY.Thick.FilmCasting.Common.FlyADIODefine;

namespace FLY.Thick.FilmCasting.Server
{

    public class TDGage : FLY.Thick.Base.IService.ITDGageService
    {
        #region 延时推送 MARKNO
        const int MARKNO_UPDATEV = 1;
        const int MARKNO_UPDATEBOLTMAP = 2;
        #endregion

        #region 初始化------------------------------------------------------------------
        /// <summary>
        /// 参数目录 m_path;数据文件的 根目录默认是 "Gage1", 不能有 @"\"
        /// 目前也是对外的服务器目录
        /// </summary>
        public string mParamDirectory;

        #endregion

        #region 数据--------------------------------------------------------------------

        /// <summary>
        /// 当前基本简单参数
        /// </summary>
        public DynArea DynArea { get; private set; }


        /// <summary>
        /// 设备参数
        /// </summary>
        public InitParam initParam;

        /// <summary>
        /// 膜位置检测
        /// </summary>
        public FilmPositionDetect filmPositionDetect;

        /// <summary>
        /// 运行参数
        /// </summary>
        public FilmCastingProfileParam profileParam;

        /// <summary>
        /// 运行参数的载体
        /// </summary>
        public FilmCastingProfile profile;

        /// <summary>
        /// 螺丝位分区数据
        /// </summary>
        public BoltMapFilmCasting boltmap;

        /// <summary>
        /// 边界查找，由 boltmap 独立出来的功能
        /// </summary>
        public BorderSearch borderSearch;

        /// <summary>
        /// AD曲线
        /// </summary>
        public CurveCollection curve;

        /// <summary>
        /// 剔除
        /// </summary>
        public Reject reject;

        /// <summary>
        /// 报警系统
        /// </summary>
        public FLY.OBJComponents.Server.WarningSystem2 warning;

        /// <summary>
        /// 扫描报警
        /// </summary>
        public ScanWarning scanWarning;

        #region 运行模式

        /// <summary>
        /// AD卡
        /// </summary>
        public FlyADBase.FlyAD7 flyAd;
        public FlyAdService flyAdService;
        /// <summary>
        /// 样品修正
        /// </summary>
        public GSample getSample;
        /// <summary>
        /// GM管理器
        /// </summary>
        GageModeManager gmManager;
        /// <summary>
        /// 断开连接
        /// </summary>
        GM_Disconnected gmDisconnected;

        /// <summary>
        /// 暂停扫描
        /// </summary>
        GM_Pause gmPause;
        /// <summary>
        /// 自动启动扫描
        /// </summary>
        GM_AutoScan gmAutoScan;

        /// <summary>
        /// 前进
        /// </summary>
        GM_Forward gmForw;
        /// <summary>
        /// 后退
        /// </summary>
        GM_Backward gmBackw;
        /// <summary>
        /// 归零
        /// </summary>
        GM_Origin gmOrg;
        /// <summary>
        /// 停止
        /// </summary>
        GM_Stop gmStop;
        /// <summary>
        /// 运行到目标位置
        /// </summary>
        GM_Goto gmRunto;

        /// <summary>
        /// 机架校正模式，参数
        /// </summary>
        public GM_ScanCorr gmScanCorr;

        /// <summary>
        /// 正常扫描模式
        /// </summary>
        public GM_Scan gmScan;

        /// <summary>
        /// 定点模式
        /// </summary>
        public GM_Fix gmFix;

        /// <summary>
        /// 机架信息，不同于机架校正
        /// </summary>
        public GM_GageInfo gmGageInfo;
        #endregion

        /// <summary>
        /// 系统参数
        /// </summary>
        public SysParam sysParam;

        #region BULKDATA,历史数据
        DbModel dbModel;
        public HistoryDb historyDb;
        LocalDb localDb;
        public BulkDb bulkDb;

        #endregion

        #endregion


        void CheckBorderSearch()
        {
            if ((borderSearch.Valid.Begin < 0) || (borderSearch.Valid.Begin > initParam.PosLength))
            {
                borderSearch.Enable = false;
            }

            if ((borderSearch.Valid.End < 0) || (borderSearch.Valid.End > initParam.PosLength))
            {
                borderSearch.Enable = false;
            }
        }
        public TDGage(string nam)
        {
            mParamDirectory = nam;// @"D:\" + m_name;

            if (!System.IO.Directory.Exists(mParamDirectory))
            {
                System.IO.Directory.CreateDirectory(mParamDirectory);
            }
            System.Environment.CurrentDirectory = mParamDirectory;

            #region create
            sysParam = new SysParam(null);//系统参数

            initParam = new InitParam()
            {
                DbDirPath = @"D:\film_casting_data"
            };
            if (!initParam.Load())
                initParam.Save();

            initParam.HasHold = false;
            initParam.HasProfileSample = false;
            initParam.HasPunch = false;
            initParam.HasVSign = false;
            initParam.HasHSign = false;
            initParam.HasScanCorr = true;


            profile = new FilmCastingProfile();//运行配置参数
            profileParam = profile.Param;
            borderSearch = new BorderSearch(null);//边界查找
            boltmap = new BoltMapFilmCasting();//分区信息

            

            curve = new CurveCollection(null);//AD转thick

            reject = new Reject(null);


            dbModel = new DbModel();
            localDb = new LocalDb();
            historyDb = new HistoryDb();
            bulkDb = new BulkDb();


            DynArea = new DynArea();

            filmPositionDetect = new FilmPositionDetect();

            warning = new OBJComponents.Server.WarningSystem2();
            scanWarning = new ScanWarning();

            flyAd = new FlyAD7();
            flyAdService = new FlyAdService();
            gmManager = new GageModeManager();
            gmFix = new GM_Fix();
            gmAutoScan = new GM_AutoScan();
            gmDisconnected = new GM_Disconnected();
            gmPause = new GM_Pause();
            gmForw = new GM_Forward();
            gmBackw = new GM_Backward();
            gmRunto = new GM_Goto();
            gmOrg = new GM_Origin();
            gmStop = new GM_Stop();
            gmGageInfo = new GM_GageInfo();
            gmScanCorr = new GM_ScanCorr();
            getSample = new GSample();
            gmScan = new GM_Scan();
            #endregion



        }

        void updateBoltmap() 
        {
            FObjBase.PollModule.Current.Poll_JustOnce(() =>
            {
                boltmap.Init(
                    initParam.Encoder1_mmpp,
                    profileParam.LeftEmptyBolts,
                    profileParam.RightEmptyBolts,
                    profileParam.UniformShrinkPercent);
            }, this, MARKNO_UPDATEBOLTMAP);
        }
        public async Task Init() 
        {
            #region 配置



            //Boltmap 配置----------------------------------------
            Misc.BindingOperations.SetBinding(initParam, nameof(InitParam.PosLength), boltmap, nameof(boltmap.PosLength));

            boltmap.Init(
                initParam.Encoder1_mmpp,
                profileParam.LeftEmptyBolts,
                profileParam.RightEmptyBolts,
                profileParam.UniformShrinkPercent);

            initParam.PropertyChanged += (s, e) =>
            {
                if (e.PropertyName == nameof(initParam.Encoder1_mmpp))
                {
                    updateBoltmap();
                }
            };
            profileParam.PropertyChanged += (s, e) =>
            {
                if ((e.PropertyName == nameof(profileParam.LeftEmptyBolts)) ||
                    (e.PropertyName == nameof(profileParam.RightEmptyBolts)) ||
                    (e.PropertyName == nameof(profileParam.UniformShrinkPercent)))
                {
                    updateBoltmap();
                }
            };

            //BorderSearch 配置----------------------------------------
            #region
            borderSearch.Init(warning);
            //检测边界查找参数
            CheckBorderSearch();
            borderSearch.PropertyChanged += (s, e) =>
            {
                if (e.PropertyName == nameof(BorderSearch.Valid))
                {
                    CheckBorderSearch();
                }
            };

            initParam.PropertyChanged += (s, e) =>
            {
                if (e.PropertyName == nameof(initParam.PosLength))
                {
                    CheckBorderSearch();
                }
            };

            Misc.BindingOperations.SetBinding(borderSearch, new string[] { nameof(borderSearch.Width) },
                () =>
                {
                    DynArea.Width = borderSearch.Width * initParam.Encoder1_mmpp;
                });
            initParam.PropertyChanged += (s, e) =>
            {
                if (e.PropertyName == nameof(initParam.Encoder1_mmpp))
                {
                    DynArea.Width = borderSearch.Width * initParam.Encoder1_mmpp;
                }
            };

            //有效范围
            Misc.BindingOperations.SetBinding(initParam, new string[] { nameof(initParam.PosLength) },
                () =>
                {
                    borderSearch.Valid = new RangeStruct(0, initParam.PosLength - 1);
                });
            #endregion

            //数据库 配置----------------------------------------
            #region
            bool ret_db;
            dbModel.SetDBPath(Path.Combine(initParam.DbDirPath, "thickness.sqlite3"));

            ret_db = await Task.Factory.StartNew(() =>
            {
                var ret_db_load = dbModel.Init();

                if (initParam.DBKeepMonth > 0)
                {
                    //不备份

                    //删除不需要的备份数据
                    dbModel.KeepBackupSize(initParam.DBKeepMonth);

                    //备份上一个月之前的数据到 yyyy-MM 文件夹
                    dbModel.BackupBbInSize(initParam.DBKeepMonth);
                }
                //当前的数据库只保存上个月与这个月的数据
                dbModel.KeepDBSize(1);
                return ret_db_load;
            });


            historyDb.Init(dbModel, localDb);
            bulkDb.Init(historyDb, localDb, dbModel);

            warning.Init(historyDb.ErrorBuffer);

            if (!ret_db)
            {
                //表加载异常
                warning.Add(
                    ERRNOs.Instance.BASE_ERRNO_DB.Code,
                    ERRNOs.Instance.BASE_ERRNO_DB.Descrption);

                //只为记录一下，不然它显示出来，所以立刻删除
                warning.Remove(
                    ERRNOs.Instance.BASE_ERRNO_DB.Code);
            }

            //数据库备份检查
            BackupDbCheckInit();
            #endregion



            //DynArea 配置----------------------------------------
            DynArea.PropertyChanged += new PropertyChangedEventHandler(mDynArea_PropertyChanged);

            //GageModeManager 配置----------------------------------------
            Misc.BindingOperations.SetBinding(
                gmManager, nameof(gmManager.State),
                DynArea, nameof(DynArea.ControllerState));


            //FlyAd7 配置----------------------------------------
            #region
            if (!flyAd.Load())
                flyAd.Save();

            flyAd.Connect();

            Misc.BindingOperations.SetBinding(flyAd, nameof(flyAd.HardwareVersion), () => {
                FlyADIODefine.Instance.SerVersion(flyAd.HardwareVersion);
            });

            Misc.BindingOperations.SetBinding(initParam, nameof(initParam.PosLength), flyAd, nameof(flyAd.PosLen));


            Misc.BindingOperations.SetBinding(flyAd, nameof(flyAd.IStatus), DynArea, nameof(DynArea.IStatus));
            Misc.BindingOperations.SetBinding(flyAd, nameof(flyAd.OStatus), DynArea, nameof(DynArea.OStatus));
            Misc.BindingOperations.SetBinding(flyAd, nameof(flyAd.Position), DynArea, nameof(DynArea.Position));

            Misc.BindingOperations.SetBinding(flyAd, nameof(flyAd.Position), () => {
                DynArea.PosMm = flyAd.Position * initParam.Encoder1_mmpp;//mm
            });

            Misc.BindingOperations.SetBinding(flyAd, nameof(flyAd.Position2), DynArea, nameof(DynArea.Position2));
            Misc.BindingOperations.SetBinding(flyAd, nameof(flyAd.Surplus), DynArea, nameof(DynArea.Hrs));
            Misc.BindingOperations.SetBinding(flyAd, nameof(flyAd.IsConnected), DynArea, nameof(DynArea.FLYADIsConnect));

            Misc.BindingOperations.SetBinding(flyAd, nameof(flyAd.PosOfGrid), initParam, nameof(initParam.PosOfGrid));

            Misc.BindingOperations.SetBinding(flyAd, nameof(flyAd.Speed), () => {
                double speed = flyAd.Speed * initParam.Encoder1_mmpp;//mm/s
                speed = speed * 60 / 1000;//m/min
                DynArea.Velocity = speed;
            });

            Misc.BindingOperations.SetBinding(
                flyAd, new string[] { nameof(flyAd.Ratio02), nameof(flyAd.Ratio01) },
                () => {
                    initParam.Speed1Scale = (double)flyAd.Ratio02 / flyAd.Ratio01;
                });

            Misc.BindingOperations.SetBinding(initParam, new string[] {
                nameof(initParam.SVelocity),
                nameof(initParam.ATime),
                nameof(initParam.DTime),
                nameof(initParam.HVelocity1),
                nameof(initParam.HVelocity2)
            }, delegate ()
            {
                PollModule.Current.Poll_JustOnce(delegate ()
                {
                    flyAd.SetPosParam(0xffffffff, initParam.SVelocity, initParam.ATime, initParam.DTime, initParam.HVelocity1, initParam.HVelocity2);

                }, this, MARKNO_UPDATEV);
            });

            Misc.BindingOperations.SetBinding(flyAd, new string[] { nameof(flyAd.IsConnected) },
                delegate ()
                {
                    if (flyAd.IsConnected == true)
                    {
                        //还需要在flyad 重新连接上时，设置！！！！！
                        PollModule.Current.Poll_JustOnce(delegate ()
                        {
                            flyAd.SetPosParam(0xffffffff, initParam.SVelocity, initParam.ATime, initParam.DTime, initParam.HVelocity1, initParam.HVelocity2);

                        }, this, MARKNO_UPDATEV);
                    }
                });

            //数据有效----------------------------------------
            flyAd.IStatusChangedEvent += (s, e) =>
            {
                if (initParam.DataValidSrc != DATAVALIDSRC.BYINPUT)
                    return;

                if (Misc.MyBase.CHECKBIT(e.IChanged, FlyADIODefine.Instance.InNo_DataValid))
                {
                    if (!Misc.MyBase.CHECKBIT(e.IStatus, FlyADIODefine.Instance.InNo_DataValid))
                        DynArea.DataValid = false;
                    else
                        DynArea.DataValid = true;
                }
            };
            Misc.BindingOperations.SetBinding(
                initParam, nameof(initParam.DataValidSrc),
                update_datavalid);

            flyAdService.Init(flyAd, Ad2Thk);
            #endregion

            //FilmPositionDetect 配置----------------------------------------
            #region
            filmPositionDetect.Init(flyAd);
            Misc.BindingOperations.SetBinding(initParam, nameof(initParam.FilmVThreshold), filmPositionDetect, nameof(filmPositionDetect.FilmVThreshold));
            Misc.BindingOperations.SetBinding(initParam, nameof(initParam.FilmVSrc), filmPositionDetect, nameof(filmPositionDetect.FilmVSrc));
            Misc.BindingOperations.SetBinding(initParam, nameof(initParam.Encoder2_mmpp), filmPositionDetect, nameof(filmPositionDetect.Encoder2_mmpp));
            Misc.BindingOperations.SetBinding(initParam, nameof(initParam.MmOfR), filmPositionDetect, nameof(filmPositionDetect.MmOfR));



            Misc.BindingOperations.SetBinding(filmPositionDetect, nameof(filmPositionDetect.FilmPosition), DynArea, nameof(DynArea.FilmPosition));
            Misc.BindingOperations.SetBinding(filmPositionDetect, nameof(filmPositionDetect.FilmVelocity), DynArea, nameof(DynArea.FilmVelocity));
            #endregion


            //WarningSystem 配置----------------------------------------
            warning.PropertyChanged += (s, e) =>
            {
                if (e.PropertyName == nameof(warning.IsRinging))
                {
                    flyAd.SetOutputBit(FlyADIODefine.Instance.OutNo_Alarm, !warning.IsRinging);
                }
            };

            //ScanWarning 配置----------------------------------------
            scanWarning.Init(warning, profileParam, bulkDb, DynArea);

            //GM_Fix 配置----------------------------------------
            gmFix.Init(flyAd, DynArea, Ad2Thk);
            gmManager.AddGM(gmFix);

            //GM_AutoScan 配置----------------------------------------
            gmAutoScan.Init(flyAd, StartP1);
            Misc.BindingOperations.SetBinding(
                gmAutoScan, nameof(gmAutoScan.Counter),
                DynArea, nameof(DynArea.AutoScanCounter));
            gmManager.AddGM(gmAutoScan);


            //GM_Disconnected 配置----------------------------------------
            gmDisconnected.Init(flyAd, DynArea, gmAutoScan);
            gmManager.AddGM(gmDisconnected);

            //GM_Pause 配置----------------------------------------
            gmPause.Init(flyAd, DynArea, gmAutoScan);
            Misc.BindingOperations.SetBinding(initParam, nameof(initParam.ReStartDelay), gmPause, nameof(gmPause.Delay));
            Misc.BindingOperations.SetBinding(initParam, nameof(initParam.AutoF1F3), gmPause, nameof(gmPause.Enable));
            gmManager.AddGM(gmPause);

            //GM_Forward 配置----------------------------------------
            gmForw.Init(flyAd);
            Misc.BindingOperations.SetBinding(initParam, nameof(initParam.VJOG), gmForw, nameof(gmForw.Velocity));
            gmManager.AddGM(gmForw);


            //GM_Backward 配置----------------------------------------
            gmBackw.Init(flyAd);
            Misc.BindingOperations.SetBinding(initParam, nameof(initParam.VJOG), gmBackw, nameof(gmBackw.Velocity));
            gmManager.AddGM(gmBackw);

            //GM_Goto 配置----------------------------------------
            gmRunto.Init(flyAd);
            Misc.BindingOperations.SetBinding(initParam, nameof(initParam.VJOG), gmRunto, nameof(gmRunto.Velocity));
            gmManager.AddGM(gmRunto);

            //GM_Origin 配置----------------------------------------
            gmOrg.Init(flyAd);
            gmManager.AddGM(gmOrg);

            //GM_Stop 配置----------------------------------------
            gmStop.Init(flyAd);
            gmManager.AddGM(gmStop);

            //GM_GageInfo 配置----------------------------------------
            gmGageInfo.Init(flyAd, initParam);

            gmManager.AddGM(gmGageInfo);

            //GM_ScanCorr 配置----------------------------------------
            gmScanCorr.Init(flyAd, initParam);
            gmManager.AddGM(gmScanCorr);
            flyAd.CorrectADs = new FlyADBase.CorrectADsHandler(gmScanCorr.CorrectADs);


            //GSample 配置----------------------------------------
            getSample.Init(flyAd, gmGageInfo, warning);
            Misc.BindingOperations.SetBinding(getSample.Samples.First(), nameof(SampleCell.AD), borderSearch, nameof(borderSearch.CurrTempAD));
            Misc.BindingOperations.SetBinding(initParam, nameof(initParam.VAccuracy), getSample, nameof(getSample.Velocity));
            getSample.SampleChangedEvent += getSample_SampleChangedEvent;


            //GM_Scan 配置----------------------------------------

            gmScan.Init(flyAd,
                getSample, initParam, warning,
                boltmap, borderSearch, reject,
                DynArea, Ad2Thk,
                profileParam, filmPositionDetect,
                historyDb, bulkDb);
            gmManager.AddGM(gmScan);
            ErrNoForCheckInit();

            #endregion`

            gmFix.Start();
        }


        #region 异常检测
        class ErrNoForCheckItem
        {
            public FLY.OBJComponents.Common.ERRNO errno;
            public Func<bool> conditional;
            /// <summary>
            /// 持续时间，单位s
            /// </summary>
            public int cnt;

            int timer = -1;
            public FLY.OBJComponents.Server.WarningSystem2 mWarning;
            public void Clear()
            {
                if (timer == 0)
                {
                    mWarning.Remove(errno.Code);
                }
                timer = -1;
            }
            public void OnPoll()
            {
                if (conditional())
                {
                    if (timer < 0)
                        timer = cnt;
                    else
                    {
                        if (timer > 0)
                            timer--;

                        if (timer == 0)
                        {
                            mWarning.Add(errno.Code,errno.Descrption);
                        }
                    }
                }
                else
                {
                    Clear();
                }
            }
        }

        List<ErrNoForCheckItem> ErrNoForCheckItems = new List<ErrNoForCheckItem>();

        public event PropertyChangedEventHandler PropertyChanged;

        void ErrNoForCheckInit()
        {
            #region 时间触发的报警
            ErrNoForCheckItems.Add(//AD值太小
                new ErrNoForCheckItem()
                {
                    errno = ERRNOs.Instance.BASE_ERRNO_AD_MIN,
                    cnt = 20,
                    conditional = delegate ()
                    {
                        return DynArea.AD < (DynArea.ADMax * 0.01);
                    }
                });

            ErrNoForCheckItems.Add(//AD值太大
                new ErrNoForCheckItem()
                {
                    errno = ERRNOs.Instance.BASE_ERRNO_AD_MAX,
                    cnt = 20,
                    conditional = delegate ()
                    {
                        return (DynArea.AD > (DynArea.ADMax * 0.98));
                    }
                });

            ErrNoForCheckItems.Add(//限位
                new ErrNoForCheckItem()
                {
                    errno = ERRNOs.Instance.BASE_ERRNO_LIMIT,
                    cnt = 2,
                    conditional = delegate ()
                    {
                        if (flyAd.MotorType == FlyADBase.MOTORTYPE.VF0)
                            return false;
                        return (
                        (Misc.MyBase.CHECKBIT(DynArea.IStatus, FlyADIODefine.Instance.InNo_Limit_Forw) == true)
                        || (Misc.MyBase.CHECKBIT(DynArea.IStatus, FlyADIODefine.Instance.InNo_Limit_Backw) == true));
                    }
                });

            ErrNoForCheckItems.Add(//急停
                new ErrNoForCheckItem()
                {
                    errno = ERRNOs.Instance.BASE_ERRNO_EMERGENCY,
                    cnt = 2,
                    conditional = delegate ()
                    {
                        return (
                        (Misc.MyBase.CHECKBIT(DynArea.IStatus, FlyADIODefine.Instance.InNo_Manual_Forw) == false)
                        || (Misc.MyBase.CHECKBIT(DynArea.IStatus, FlyADIODefine.Instance.InNo_Manual_Backw) == false));
                    }
                });

            foreach (ErrNoForCheckItem item in ErrNoForCheckItems)
            {
                item.mWarning = warning;
            }

            FObjBase.PollModule.Current.Poll_Config(
                FObjBase.PollModule.POLL_CONFIG.ADD,
                onpoll_checkErrNo, TimeSpan.FromSeconds(1));

            #endregion

            #region 状态触发的报警
            Misc.BindingOperations.SetBinding(DynArea, nameof(DynArea.Hrs), () =>
            {
                if (DynArea.Hrs < 48 && DynArea.Hrs > 0)//授权限制提醒
                {
                    warning.Add(
                        ERRNOs.Instance.BASE_ERRNO_LICENSE_TIP.Code,
                        ERRNOs.Instance.BASE_ERRNO_LICENSE_TIP.Descrption);
                }
                else
                {
                    warning.Remove(ERRNOs.Instance.BASE_ERRNO_LICENSE_TIP.Code);
                }
            });

            Misc.BindingOperations.SetBinding(DynArea, nameof(DynArea.SecuteLock), () =>
            {
                if (DynArea.SecuteLock)
                {
                    warning.Add(
                        ERRNOs.Instance.BASE_ERRNO_LICENSE.Code,
                        ERRNOs.Instance.BASE_ERRNO_LICENSE.Descrption);
                }
                else
                {
                    warning.Remove(ERRNOs.Instance.BASE_ERRNO_LICENSE.Code);
                }
            });

            //AD盒连接断开
            Misc.BindingOperations.SetBinding(DynArea, nameof(DynArea.FLYADIsConnect), () =>
            {
                if (!DynArea.FLYADIsConnect)
                {
                    warning.Add(
                        ERRNOs.Instance.BASE_ERRNO_FLYAD7DISCONNECTED.Code,
                        ERRNOs.Instance.BASE_ERRNO_FLYAD7DISCONNECTED.Descrption);
                }
                else
                {
                    warning.Remove(ERRNOs.Instance.BASE_ERRNO_FLYAD7DISCONNECTED.Code);
                }
            });


            #endregion
        }


        void onpoll_checkErrNo() //1秒执行一次
        {
            if (!DynArea.FLYADIsConnect)
            {
                foreach (ErrNoForCheckItem item in ErrNoForCheckItems)
                    item.Clear();
            }
            else
            {
                foreach (ErrNoForCheckItem item in ErrNoForCheckItems)
                    item.OnPoll();
            }
        }
        #endregion

        void mDynArea_PropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            if (e.PropertyName == nameof(DynArea.FilmVelocity))
            {
                update_datavalid();
            }
        }

        void update_datavalid()
        {
            switch (initParam.DataValidSrc)
            {
                case DATAVALIDSRC.VALID:
                    DynArea.DataValid = true;
                    break;
                case DATAVALIDSRC.INVALID:
                    DynArea.DataValid = false;
                    break;
                case DATAVALIDSRC.BYEN2:
                    {
                        if (DynArea.FilmVelocity >= initParam.FilmVThreshold)
                            DynArea.DataValid = true;
                        else
                            DynArea.DataValid = false;
                    }
                    break;
                case DATAVALIDSRC.BYINPUT:
                    {
                        if (!Misc.MyBase.CHECKBIT(flyAd.IStatus, FlyADIODefine.Instance.InNo_DataValid))
                            DynArea.DataValid = false;
                        else
                            DynArea.DataValid = true;
                    }
                    break;
            }
        }


        public double Ad2Thk(int ad)
        {
            if (Misc.MyBase.ISVALIDATA(ad))
            {
                double thk;
                if (getSample.Enable)//动态温修
                    thk = curve.AD2Value(ad, AD2ValueFlag.Revised);
                else
                    thk = curve.AD2Value(ad, AD2ValueFlag.NoRevised);

                thk = profile.Param.K * thk + profile.Param.B;
                thk = Math.Round(thk, 2);
                return thk;
            }
            return double.NaN;
        }

        void getSample_SampleChangedEvent(FLY.Thick.Base.Server.GSample _gsample)
        {
            var gsample = _gsample;
            CurveCollection pCurve = curve;

            if (gsample.OK())//这个很重要！！！！！！！
            {

                historyDb.AddSample(
                    new Lc_Sample()
                    {
                        Time = DateTime.Now,
                        SampleADs = gsample.Samples.Select(c => c.AD).ToArray()
                    });

                List<CurveCollection.ExChange> list = new List<CurveCollection.ExChange>();
                for (int i = 0; i < gsample.Samples.Count(); i++)
                {
                    var sample = gsample.Samples[i];
                    if ((sample.Enable) && (!sample.JustForCheck) && (sample.AD > 0))
                    {
                        list.Add(new CurveCollection.ExChange() { OrgAD = sample.OrgAD, CurrAD = sample.AD });
                    }
                }
                pCurve.ModifyExChange(list);
                pCurve.ReviseCurve();

                for (int i = 0; i < gsample.Samples.Count(); i++)
                {
                    var sample = gsample.Samples[i];
                    if ((sample.Enable) && (sample.AD > 0))
                    {
                        int value = (int)(curve.AD2Value(sample.AD, AD2ValueFlag.Revised) * 100);
                        sample.SampleValue = value;
                    }
                }
            }
        }


        #region 数据库备份检测
        DispatcherTimer backupDbTimer;
        DateTime StartupTime;
        void BackupDbCheckInit() 
        {
            StartupTime = DateTime.Now;

            //定时检查提示
            backupDbTimer = new DispatcherTimer();
            backupDbTimer.Interval = TimeSpan.FromHours(1);
            backupDbTimer.Tick += BackupDbTimer_Tick;
            backupDbTimer.Start();
        }


        private void BackupDbTimer_Tick(object sender, EventArgs e)
        {
            //只有在9:00 到 21:00 才会检查，避免深夜出问题
            if (DateTime.Now.Hour < 9 || DateTime.Now.Hour > 20)
                return;

            if (DateTime.Now - StartupTime > TimeSpan.FromDays(28) && DateTime.Now.Month != StartupTime.Month) 
            {
                //已经连续开机1个月，需要重新启动程序
                warning.Add(
                    ERRNOs.Instance.BASE_ERRNO_DB_BACKUP.Code,
                    ERRNOs.Instance.BASE_ERRNO_DB_BACKUP.Descrption);
            }
        }
        #endregion


        #region ITDGageService

        public void StartP1()
        {
            gmScan.Start();
        }

        public void StartP2(STARTP2_MODE mode)
        {
            StartP2(mode, 0);
        }
        public void StartP2(STARTP2_MODE mode, int targetpos)
        {
            switch (mode)
            {
                case STARTP2_MODE.ORG:
                    gmOrg.Start();
                    break;
                case STARTP2_MODE.STOP:
                    gmStop.Start();
                    break;
                case STARTP2_MODE.FORW:
                case STARTP2_MODE.FORW_UNTIL_STOP:
                    gmForw.Start();
                    break;
                case STARTP2_MODE.BACKW:
                case STARTP2_MODE.BACKW_UNTIL_STOP:
                    gmBackw.Start();
                    break;
                case STARTP2_MODE.RUNTO:
                    gmRunto.Start(targetpos);
                    break;
            }
        }


        #endregion
    }
}
