using Siger.ApiDashboard.Result;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace Siger.ApiDashboard.Utilities
{
    /// <summary>
    /// 
    /// </summary>
    public class AccQuantityCalculationHelper
    {
        /// <summary>
        ///  做差
        /// </summary>
        /// <param name="source"></param>
        /// <param name="rounding">保留小数点</param>
        /// <returns></returns>
        public static List<double>GetRang(List<double>source, int rounding = 4)
        {
            var rang= new List<double>();
            for (int i=0;i<source.Count;i++)
            {
                if (i == 0)
                    continue;
                var data = Math.Round(source[i] - source[i - 1], rounding);
                rang.Add(Math.Abs(data));
                //不取绝对值
                //rang.Add(data);
            }
            return rang;
        }
        /// <summary>
        /// 单值上控制线
        /// </summary>
        /// <param name="x">样本均值</param>
        /// <param name="mR">Rang均值</param>
        /// <param name="rounding">保留小数点</param>
        /// <returns></returns>
        public static double UCLx(double x,double mR, int rounding = 4)
        {
            if (x == 0 || mR == 0)
                return 0d;
            var constant = 1.128;
            return Math.Round( x + (3 * (mR / constant)), rounding);
        }
        /// <summary>
        /// 单值下控制线
        /// </summary>
        /// <param name="x"></param>
        /// <param name="mR">Rang均值</param>
        /// <param name="rounding">保留小数点</param>
        /// <returns></returns>
        public static double LCLx(double x, double mR, int rounding = 4)
        {
            if (x == 0 || mR == 0)
                return 0d;
            var constant = 1.128;
            return Math.Round(x - (3 * (mR / constant)), rounding);
        }
        /// <summary>
        /// 移动极值差 上控制线
        /// </summary>
        /// <param name="mR">所有Rang 的均值</param>
        /// <param name="rounding">保留小数点</param>
        /// <returns></returns>
        public static double UCLr(double mR, int rounding = 4)
        {
            var constant = 3.267;
            return Math.Round( constant * mR, rounding);
        }

        /// <summary>
        /// 获取数组标准差
        /// </summary>
        /// <param name="sample">样本数组</param>
        /// <param name="sampleMean">均差</param>
        /// <param name="rounding">保留小数点</param>
        /// <returns></returns>
        public static double GetVariance(List<double> sample, double sampleMean,int rounding = 4)
        {
            var sumMr = 0d;
            if (sample.Count == 0)
                return sumMr;
            foreach(var s in sample)
            {
                sumMr += Math.Pow(s - sampleMean,2);
            }
            //var sigma = Math.Sqrt(sumMr / sample.Count());
            //计算标准差总和需要减一
            var sigma = Math.Sqrt(sumMr / (sample.Count() - 1));
            return Math.Round(sigma, rounding);
        }

        /// <summary>
        /// 质量数据 Echart 图拼装 左1
        /// </summary>
        /// <param name="sample"></param>
        /// <param name="uCLx"></param>
        /// <param name="lCLx"></param>
        /// <param name="sampleMean"></param>
        /// <returns></returns>
        public static AccQualityDataleftmiddle accQualityMiddle(List<double>sample,double uCLx,double lCLx,double sampleMean)
        {
            var result = new AccQualityDataleftmiddle {
                xAxis = new List<int>(),
                Sample=new List<double>(),
                SampleMeanArray=new List<double>(),
                UCLArray=new List<double>(),
                LCLArray=new List<double>()
            };
            var step = 0;
            foreach(var s in sample)
            {
                step += 1;
                result.xAxis.Add(step);
                result.Sample = sample;
                result.SampleMeanArray.Add(sampleMean);
                result.UCLArray.Add(uCLx);
                result.LCLArray.Add(lCLx);
            }
            return result;
        }

        /// <summary>
        /// 质量数据 Echart 图拼装 左2
        /// </summary>
        /// <param name="rang"></param>
        /// <param name="rangUCL"></param>
        /// <param name="rangLCL"></param>
        /// <param name="rangMean"></param>
        /// <returns></returns>
        public static AccQualityDataleftbottom accQualityLefeBottom(List<double> rang, double rangUCL, double rangLCL, double rangMean)
        {
            var result = new AccQualityDataleftbottom {
                Range = new List<double>(),
                RangeLCLArray=new List<double>(),
                RangeMeanArray=new List<double>(),
                RangeUCLArray=new List<double>(),
                xAxis=new List<int>()
            };
            var step = 0;
            foreach (var r in rang)
            {
                step += 1;
                result.xAxis.Add(step);
                result.Range = rang;
                result.RangeUCLArray.Add(rangUCL);
                result.RangeLCLArray.Add(rangLCL);
                result.RangeMeanArray.Add(rangMean);
            }
            return result;
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="sample"></param>
        /// <param name="rounding"></param>
        /// <returns></returns>
        public static List<List<double>> AccQualityDatalefttop(List<double> sample, int rounding)
        {
            var pillarsNum = 16;
            var max = sample.Max();
            var min = sample.Min();
            var minZui = sample.Min();
            var offset = (max - min) / pillarsNum;
            var result = new List<List<double>>();
            var arr = new List<double>();
            for(int i=0;i <10000;i ++)
            {
                if (min >= max)
                    break;
                if (max>min)
                {
                    min = min + offset;
                    arr.Add(min);
                }
            }
            arr.Insert(0, Math.Round(minZui, rounding));
            arr.Insert(0, Math.Round(minZui - offset, rounding));
            arr.Add(Math.Round(max + offset, rounding));
            var ret = new List<double>();
            for (int i=0;i< arr.Count;i ++)
            {
                var less= arr[i];
                var big = 0d;
                if (i < arr.Count-1)
                    big= arr[i + 1];
                else
                    big = arr[i];
                var j = 0;
                foreach(var s in sample)
                {
                    if (s>less && s <big)
                        j += 1;
                }
                ret.Add(j);
            }
            arr.Insert(0, 0);

            result.Insert(0, ret);
            result.Insert(1, arr);

            return result;
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="sampleCount"></param>
        /// <param name="sampleMean"></param>
        /// <param name="sigma"></param>
        /// <param name="cp"></param>
        /// <param name="cpk"></param>
        /// <returns></returns>
        public static AccQualityDatarightbottomleft accQualityBottomleft(int sampleCount,double sampleMean,double sigma,double cp,double cpk)
        {
            return new AccQualityDatarightbottomleft
            {
                SampleCount = sampleCount,
                SampleMean=sampleMean,
                sigma=sigma,
                cp=cp,
                cpk=cpk
            };
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="itemMax"></param>
        /// <param name="itemMin"></param>
        /// <param name="paramater"></param>
        /// <param name="cpu"></param>
        /// <param name="cpl"></param>
        /// <returns></returns>
        public static AccQualityDatarightbottomright accQualitybottomright(double itemMax,double itemMin,double paramater,double cpu,double cpl)
        {
            return new AccQualityDatarightbottomright {
                right_foot_online=itemMax,
                right_foot_offline=itemMin,
                parameterValue=paramater,
                cpu=cpu,
                cpl=cpl
            };
        }
    }
}
