using AutoMapper;
using FLY.Thick.Base.IService;
using FObjBase;
using Misc;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Linq;
namespace FLY.Thick.Base.Server
{
    //1.剔除 偏离平均值 大于 设定值
    //2.权重 滤波
    public class Reject : IRejectService, INotifyPropertyChanged
    {

        public bool Enable { get; set; }

        /// <summary>
        /// 规格范围, (value - Target)/Target > LimitRangeRatio 就会被剔除
        /// </summary>
        public double LimitRangeRatio { get; set; }

        public double ThresholdRatio { get; set; }


        public int SmoothRange { get; set; }

        public int RejectRange { get; set; }

        /// <summary>
        /// 调试数据更新时间，用于让客户端 决定什么时候 下载调试数据
        /// </summary>
        public DateTime DebugUpdateTime { get; private set; }

        private RejectDebugData rejectDebug;

        private string param_path = "reject.json";
        public Reject()
        {
            SetDefault();

        }

        public Reject(string param_path)
        {
            if (!string.IsNullOrEmpty(param_path))
                this.param_path = param_path;

            SetDefault();
            Load();
        }

        void SetDefault()
        {
            Enable = false;
            LimitRangeRatio = 0.3;
            ThresholdRatio = 0.93;

            SmoothRange = 10;
            RejectRange = 300;
        }

        public bool Load()
        {
            return RejectJsonDb.Load(param_path, this);
        }
        public bool Save()
        {
            return RejectJsonDb.Save(param_path, this);

        }
        public void Apply()
        {
            Save();
        }

        public void DoFrameFilter(double target, int posOfGrid, int start_grid, double[] frame)
        {

            var rejectDatas = (double[])frame.Clone();




            int smoothRange = SmoothRange / posOfGrid;
            if (smoothRange <= 0) smoothRange = 1;
            int len = frame.Count();

            var filterDatas = new double[len];
            //滤波
            for (int i = 0; i < len; i++)
            {
                int b = i - smoothRange;
                int e = i + smoothRange;

                if (b < 0) b = 0;
                if (e >= len) e = len - 1;
                List<double> datas = new List<double>();
                for (int j = b; j <= e; j++)
                    datas.Add(rejectDatas[j]);

                filterDatas[i] = datas.AverageNoNull();
            }


            double threshold = target * ThresholdRatio;
            double limitRange = LimitRangeRatio * target;

            bool[] bfilterdats = new bool[len];
            //阀值剔除
            for (int i = 0; i < len; i++)
            {
                if (!double.IsNaN(rejectDatas[i]))
                {
                    if (rejectDatas[i] < threshold)
                    {
                        bfilterdats[i] = true;
                    }
                    else if (Math.Abs(target - rejectDatas[i]) > limitRange)
                    {
                        bfilterdats[i] = true;
                    }
                }
            }


            int reject_b_idx = -1;
            int reject_e_idx = -1;
            //半径内全部删除
            int reject_range = RejectRange / posOfGrid;
            if (reject_range < 0)
                reject_range = 0;

            for (int i = 0; i < len; i++)
            {
                if (!bfilterdats[i])
                {
                    //之前有需要剔除的
                    if (reject_b_idx != -1)
                    {
                        int b = reject_b_idx - reject_range;
                        int e = reject_e_idx + reject_range;
                        if (b < 0) b = 0;
                        if (e >= len) e = len - 1;
                        for (int j = b; j <= e; j++)
                        {
                            rejectDatas[j] = double.NaN;
                        }
                        reject_b_idx = -1;
                        i = e;
                    }
                }
                else
                {
                    if (reject_b_idx == -1)
                    {
                        reject_b_idx = i;
                    }
                    reject_e_idx = i;
                }
            }
            if (reject_b_idx != -1)
            {
                int b = reject_b_idx - reject_range;
                int e = reject_e_idx + reject_range;
                if (b < 0) b = 0;
                if (e >= len) e = len - 1;
                for (int j = b; j <= e; j++)
                {
                    rejectDatas[j] = double.NaN;
                }
                reject_b_idx = -1;
            }

            if (Enable)
            {
                Array.Copy(rejectDatas, 0, frame, 0, len);
            }

            var rejectDebug = new RejectDebugData
            {
                posOfGrid = posOfGrid,
                start_grid = start_grid,
                target = target,
                filterDatas = filterDatas,
                rejectDatas = rejectDatas,
            };

            this.rejectDebug = rejectDebug;
            this.DebugUpdateTime = DateTime.Now;


        }
        public void GetDebugData(AsyncCBHandler asyncDelegate, object asyncContext)
        {
            asyncDelegate?.Invoke(asyncContext, rejectDebug);
        }

        #region INotifyPropertyChanged 成员

        public event PropertyChangedEventHandler PropertyChanged;

        #endregion

    }

    public class RejectJsonDb
    {
        static Mapper Mapper { get; } = new AutoMapper.Mapper(new MapperConfiguration(c =>
        {
            c.CreateMap<Reject, RejectJsonDb>().ReverseMap();
        }));

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

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

            }
            return false;
        }



        public bool Enable { get; set; }

        public double LimitRangeRatio { get; set; }

        public double ThresholdRatio { get; set; }

        public int SmoothRange { get; set; }

        public int RejectRange { get; set; }

    }
}
