using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using System.ComponentModel;
using FlyADBase;
using FLY.Thick.Base.IService;
using AutoMapper;
using System.IO;
using Newtonsoft.Json;
using FObjBase;

namespace FLY.Thick.Base.Server
{

    public class GM_GageInfo : GM_Base, IGageInfoService
    {
        /// <summary>
        /// 速度
        /// </summary>
        public UInt32 Velocity { get; set; } = 1000;

        #region IGageInfoService 接口

        /// <summary>
        /// 数据好了！！！！
        /// 当 flyad7 的poslen, posOfGrid 发生变化时，DataOK = false, 需要重新记录。
        /// </summary>
        public bool DataOK { get; private set; }

        /// <summary>
        /// 机架总长，脉冲
        /// </summary>
        public int PosLen { get; private set; } = 9123;

        /// <summary>
        /// 1个grid = N个pos
        /// </summary>
        public int PosOfGrid { get; private set; } = 11;

        /// <summary>
        /// 数据更新时间
        /// </summary>
        public DateTime[] UpdateTimes { get; private set; }

        /// <summary>
        /// 0~100
        /// </summary>
        public int Progress { get; private set; }
        #endregion


        string file_path;

        ScanMotion2 scanMotion;
        protected InitParam initParam;
        public GageInfoData Data;

        public GM_GageInfo():this("gageinfo.json")
        {

        }
        public GM_GageInfo(string param_path)
        {
            GMState = FLY.Thick.Base.Common.CTRL_STATE.GAGEINFO;
            this.file_path = param_path;

            Load();
        }
        public void Init(FlyAD7 flyad, InitParam initParam)
        {
            base.Init(flyad);
            this.initParam = initParam;

            Misc.BindingOperations.SetBinding(initParam, nameof(initParam.VAccuracy), this, nameof(Velocity));

            scanMotion = new ScanMotion2();

            scanMotion.Init(flyad);
            scanMotion.EndEvent += GM_GageInfo_EndEvent;
            scanMotion.PropertyChanged += GM_GageInfo_PropertyChanged;

            UpdateTimes = new DateTime[2];
            updateDataOK();

            initParam.PropertyChanged += new PropertyChangedEventHandler(initParam_PropertyChanged);


        }

        /// <summary>
        /// 数据录制，记下来回扫描的AD值数组
        /// </summary>
        public override void Start()
        {
            base.Start();
            if (!IsRunning)
                return;

            Progress = 0;
            DataOK = false;
            PosOfGrid = initParam.PosOfGrid;
            PosLen = initParam.PosLength;
            Data = new GageInfoData();
            for (int i = 0; i < 2; i++)
                UpdateTimes[i] = DateTime.Now;
            NotifyPropertyChanged(nameof(UpdateTimes));

            scanMotion.Start(1, Velocity);
        }
        public override void Stop()
        {
            base.Stop();
            if (DataOK)
            {
                Progress = 100;
            }
            else
            {
                PosOfGrid = initParam.PosOfGrid;
                PosLen = initParam.PosLength;
                Data = new GageInfoData();

                for (int i = 0; i < 2; i++)
                    UpdateTimes[i] = DateTime.Now;
                NotifyPropertyChanged(nameof(UpdateTimes));
            }

            Save();

        }

        protected override void OnPoll()
        {
            if (scanMotion.OnPoll())
            {
                Stop();
            }
        }
        private void GM_GageInfo_PropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            if (e.PropertyName == nameof(ScanMotion2.Progress))
            {
                Progress = scanMotion.Progress;
            }
        }

        void initParam_PropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            if ((e.PropertyName == nameof(initParam.PosOfGrid)) ||
                (e.PropertyName == nameof(initParam.PosLength)))
            {
                updateDataOK();
            }
        }
        void updateDataOK()
        {
            if (Data == null)
            {
                DataOK = false;
                return;
            }

            if (Data.ForwData == null || Data.BackwData == null)
            {
                DataOK = false;
                return;
            }

            if ((PosOfGrid != initParam.PosOfGrid) ||
                (PosLen != initParam.PosLength))
                DataOK = false;
            else
                DataOK = true;
        }

        private void GM_GageInfo_EndEvent(object obj, MiniGridEventArgs e)
        {
            DataEnd(e.direction, e.posOfGrid, e.grid_start, e.buf);
        }
        void DataEnd(Misc.DIRECTION direction, int posOfGrid, int start_grid, int[] dat)
        {
            int grid_len = PosLen / PosOfGrid;
            int[] datas = new int[grid_len];
            for (int i = 0; i < grid_len; i++)
            {
                datas[i] = Misc.MyBase.NULL_VALUE;
            }
            if (direction == Misc.DIRECTION.FORWARD)
            {
                for (int i = 0; i < dat.Length; i++)
                {
                    int grid = i + start_grid;
                    if (grid >= grid_len)
                        break;
                    datas[grid] = dat[i];
                }
                Data.ForwData = datas;
                UpdateTimes[0] = DateTime.Now;
                NotifyPropertyChanged(nameof(UpdateTimes));
            }
            else
            {
                for (int i = 0; i < dat.Length; i++)
                {
                    int grid = i + start_grid;
                    if (grid >= grid_len)
                        break;
                    datas[grid] = dat[i];

                }
                Data.BackwData = datas;
                UpdateTimes[1] = DateTime.Now;
                NotifyPropertyChanged(nameof(UpdateTimes));
            }

            updateDataOK();
        }

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

        bool Save()
        {
            return GageInfoJsonDb.Save(file_path, this);
        }

        public void GetGageInfo(int idx, AsyncCBHandler asyncDelegate, object asyncContext)
        {
            if (Data == null ||
                idx < 0 ||
                idx >= 2)
            {
                asyncDelegate(asyncContext, new GetGageInfoResponse() { Idx = idx });
                return;
            }
            var data = Data;
            var reponse = new GetGageInfoResponse()
            {
                Idx = idx,
                Data = idx % 2 == 0 ? data.ForwData : data.BackwData,
                UpdateTime = UpdateTimes[idx]
            };

            asyncDelegate(asyncContext, reponse);
        }
    }
    public class GageInfoJsonDb
    {
        static Mapper Mapper { get; } = new AutoMapper.Mapper(new MapperConfiguration(c =>
        {
            c.CreateMap<GM_GageInfo, GageInfoJsonDb>().ReverseMap();
        }));

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

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

            }
            return false;
        }


        /// <summary>
        /// 机架总长，脉冲
        /// </summary>
        public int PosLen { get; set; } = 9123;

        /// <summary>
        /// 1个grid = N个pos
        /// </summary>
        public int PosOfGrid { get; set; } = 11;

        public GageInfoData Data;
    }
}
