using FLY.OBJComponents.Server;
using FLY.Thick.Base.Common;
using FLY.Thick.Base.Server;
using FLY.Thick.Blowing.Common;
using FLY.Thick.Blowing.Server;
using FLY.Thick.Blowing.Server.Model;
using FlyADBase;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Threading.Tasks;
using System.Windows.Threading;
using ERRNOs = FLY.Thick.Base.Common.ERRNOs;
using FlyADIODefine = FLY.Thick.Blowing.Common.FlyADIODefine;

namespace FLY.Thick.Blowing360.Server
{
    public class TDGage : FLY.Thick.Base.IService.ITDGageService
    {
        #region 参数--------------------------------------------------------------------
        #region 初始化------------------------------------------------------------------
        /// <summary>
        /// 参数目录 m_path;数据文件的 根目录默认是 "Gage1", 不能有 @"\"
        /// 目前也是对外的服务器目录
        /// </summary>
        public string mParamDirectory;

        #endregion

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

        /// <summary>
        /// 当前基本简单参数
        /// </summary>
        public DynArea DynArea => dynArea;
        private DynArea dynArea;

        /// <summary>
        /// 运行参数
        /// </summary>
        public BlowingFixProfile profile;
        BlowingFixProfileParam profileParam;

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

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

        #region 运行模式

        /// <summary>
        /// AD卡
        /// </summary>
        public FlyADBase.FlyAD7 flyAd;
        public FlyAdService flyAdService;
        /// <summary>
        /// GM管理器
        /// </summary>
        GageModeManager gmManager;

        /// <summary>
        /// 定点模式
        /// </summary>
        public GM_Fix gmFix;
        /// <summary>
        /// 吹膜测厚模式.定点
        /// </summary>
        public GM_BlowingFix360 gmRenZiJiaFix;
        public BlowingDetect360 blowingDetect;
        /// <summary>
        /// 扫描报警系统
        /// </summary>
        public ScanWarning scanWarning;

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

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



        #region BULKDATA


        /// <summary>
        /// 数据库对象
        /// </summary>
        DbModel dbModel;
        ///// <summary>
        ///// 原始数据 数据库对象
        ///// </summary>
        //OrgDbModel orgDbModel;
        /// <summary>
        /// 数据库写操作
        /// </summary>
        public HistoryDb historyDb;
        //OrgHistoryDb orgHistoryDb;
        /// <summary>
        /// 本地数据库
        /// </summary>
        LocalDb localDb;
        /// <summary>
        /// 数据库读操作
        /// </summary>
        public BulkDb bulkDb;

        #endregion

        #endregion

        #endregion

        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:\blowingdata"
            };
            if (!initParam.Load())
                initParam.Save();

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

            profile = new BlowingFixProfile();//运行配置参数
            profileParam = profile.Param;

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


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

            dynArea = new DynArea();

            warning = new WarningSystem2();
            scanWarning = new ScanWarning();

            flyAd = new FlyAD7();
            flyAdService = new FlyAdService();
            gmManager = new GageModeManager();
            gmFix = new GM_Fix();
            gmRenZiJiaFix = new GM_BlowingFix360();
            blowingDetect = new BlowingDetect360();

            #endregion
        }
        public async Task Init()
        {
            #region 配置
            //---------------------------------------------------------------------------------------------------------------
            //数据库
            await Task.Factory.StartNew(() =>
            {
                dbModel.Init();


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

                //备份上一个月之前的数据到 yyyy-MM 文件夹
                dbModel.BackupBbInSize(12);

                //当前的数据库只保存上个月与这个月的数据
                dbModel.KeepDBSize(1);
            });

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

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


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

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

            flyAd.Connect();

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

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

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

            flyAdService.Init(flyAd, Ad2Thk);

            //WarningSystem 配置----------------------------------------
            warning.Init(historyDb.ErrorBuffer);

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

            //ScanWarning 配置----------------------------------------
            scanWarning.Init(warning, historyDb);


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


            //GM_RenZiJiaFix 配置----------------------------------------
            blowingDetect.Init(flyAd);
            gmRenZiJiaFix.Init(flyAd, blowingDetect, Ad2Thk, dynArea, profile.Param, historyDb, bulkDb);
            gmManager.AddGM(gmRenZiJiaFix);


            gmRenZiJiaFix.Start();


            ErrNoForCheckInit();

            #endregion
        }

        //void mGMRenZiJiaFix_EPCSampled(int ad)
        //{
        //    CurveCollection pCurve = curve;

        //    dynArea.SampleAD[0] = ad;
        //    List<CurveCollection.ExChange> list = new List<CurveCollection.ExChange>();
        //    if (pCurve.Curves.Count == 0)
        //        return;


        //    list.Add(new CurveCollection.ExChange() { OrgAD = pCurve.Curves[0].AD, CurrAD = ad });
        //    pCurve.ModifyExChange(list);
        //    pCurve.ReviseCurve();
        //}
        #region 异常检测
        class ErrNoForCheckItem
        {
            public FLY.OBJComponents.Common.ERRNO errno;
            public Func<bool> conditional;
            /// <summary>
            /// 持续时间,单位s
            /// </summary>
            public int cnt;

            int timer = -1;
            public 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>();
        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));
                    }
                });

            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);
                }
            });

            #endregion
        }

        void onpoll_checkErrNo() //1秒执行一次
        {
            if (!dynArea.FLYADIsConnect)
            {
                warning.Add(
                    ERRNOs.Instance.BASE_ERRNO_FLYAD7DISCONNECTED.Code,
                    ERRNOs.Instance.BASE_ERRNO_FLYAD7DISCONNECTED.Descrption);

                foreach (ErrNoForCheckItem item in ErrNoForCheckItems)
                    item.Clear();
            }
            else
            {
                warning.Remove(ERRNOs.Instance.BASE_ERRNO_FLYAD7DISCONNECTED.Code);

                foreach (ErrNoForCheckItem item in ErrNoForCheckItems)
                    item.OnPoll();
            }
        }
        #endregion

        public event PropertyChangedEventHandler PropertyChanged;

        public double Ad2Thk(int ad)
        {
            double thk = double.NaN;

            if (Misc.MyBase.ISVALIDATA(ad))
            {
                thk = curve.AD2Value(ad, AD2ValueFlag.Revised);

                thk *= profile.Param.K;
            }
            return thk;
        }


        #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()
        {

        }

        public void StartP2(STARTP2_MODE mode)
        {

        }
        public void StartP2(STARTP2_MODE mode, int targetpos)
        {

        }


        #endregion
    }
}