using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace WSDDBBrowser.Core
{

    public class TrendValue
    {
        public double Value;
        public double Position;
        public DateTime Time;
        public TrendValue(double v, double pos, DateTime t)
        {
            Value = v;
            Position = pos;
            Time = t;
        }
    }

    public class BoltValue : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;

        public double Value { get; set; }
        public double From { get; set; }
        public double To { get; set; }

        public BoltValue() { }
        public BoltValue(double from, double to, double value)
        {
            From = from;
            To = to;
            Value = value;
        }
    }

    public class Bolt : INotifyPropertyChanged, ICloneable
    {
        public double Begin { get; set; }
        public double End { get; set; }

        public event PropertyChangedEventHandler PropertyChanged;

        public Bolt(double b, double e)
        {
            Begin = b;
            End = e;
        }
        public Bolt()
        {

        }

        public object Clone()
        {
            return new Bolt(Begin, End);
        }
        public override bool Equals(object obj)
        {
            if (!(obj is Bolt))
                return false;
            Bolt bolt = obj as Bolt;
            if (bolt.Begin != Begin)
                return false;
            if (bolt.End != End)
                return false;

            return true;
        }
    }


    public class SampleValue
    {
        public double[] Values;
        public DateTime Time;
    }
    public class XY : IComparable
    {
        public double X;
        public double Y;
        public XY(double x, double y)
        {
            X = x;
            Y = y;
        }

        public int CompareTo(object obj)
        {
            XY xy = obj as XY;
            return X.CompareTo(xy.X);
        }
    }

    public static class Enumerable
    {
        //
        // 摘要:
        //     计算 System.Double 值序列的Sigma，该值可通过调用输入序列的每个元素的转换函数获取。
        //
        // 参数:
        //   source:
        //     要计算其平均值的值序列。
        //
        //   selector:
        //     应用于每个元素的转换函数。
        //
        // 类型参数:
        //   TSource:
        //     source 中的元素的类型。
        //
        // 返回结果:
        //     值序列的Sigma。
        //
        // 异常:
        //   T:System.ArgumentNullException:
        //     source 或 selector 为 null。
        //
        //   T:System.InvalidOperationException:
        //     source 中不包含任何元素。
        public static double Sigma<TSource>(this IEnumerable<TSource> source, Func<TSource, double> selector)
        {
            if (source.Count() == 0)
                return -1;
            double avg = source.Average(selector);
            double sum_pow = source.Sum((s) => Math.Pow((selector(s) - avg), 2));
            return Math.Sqrt(sum_pow / (source.Count() - 1));
        }

        public static double Sigma(this IEnumerable<double> source)
        {
            return source.Sigma(d => d);
        }
        public static double CPK<TSource>(this IEnumerable<TSource> source, Func<TSource, double> selector, double usl, double lsl)
        {
            if (source.Count() == 0)
                return -1;

            //CPK = Min（CPKu,CPKl)
            //USL(Upper specification limit): 规格上限。
            //LSL(Low specification limit): 规格下限。
            //ˉx = (x1 + x2 +...+ xn) / n : 平均值。
            //T = USL - LSL : 规格公差。
            //U = (USL + LSL) / 2：规格中心。
            //CPKu = | USL - ˉx | / 3σ 
            //CPKl = | ˉx - LSL | / 3σ

            double avg = source.Average(selector);
            double sigma3 = source.Sigma(selector) * 3;

            double CPKu = Math.Abs(usl - avg) / sigma3;
            double CPKl = Math.Abs(lsl - avg) / sigma3;
            double CPK = Math.Min(CPKu, CPKl);
            return CPK;
        }

        public static double CPK(this IEnumerable<double> source, double usl, double lsl)
        {
            return source.CPK(d => d, usl, lsl);
        }
        public static List<XY> GetHistogram<TSource>(this IEnumerable<TSource> source, Func<TSource, double> selector, double step)
        {
            List<XY> list = new List<XY>();

            foreach (var v in source)
            {
                double x = ((int)(selector(v) / step)) * step;
                XY xy = list.Find(_xy => _xy.X == x);
                if (xy != null)
                {
                    xy.Y++;
                }
                else
                {
                    xy = new XY(x, 1);
                    list.Add(xy);
                }

            }
            list.Sort();

            return list;
        }

        public static List<XY> GetHistogram(this IEnumerable<double> source, double step)
        {
            return source.GetHistogram(d => d, step);
        }
    }

    public class MultiFixInfo : INotifyPropertyChanged
    {
        public DateTime Time { get; set; }

        /// <summary>
        /// 膜上横向位置 单位mm
        /// </summary>
        public int PosInFilm { get; set; }

        /// <summary>
        /// 涂布速度 m/min
        /// </summary>
        public double Velocity { get; set; }
        /// <summary>
        /// 膜开始位置 mm
        /// </summary>
        public int FilmBegin { get; set; }
        /// <summary>
        /// 膜结束位置 mm
        /// </summary>
        public int FilmEnd { get; set; }
        public double K { get; set; }
        public double B { get; set; }

        public List<double> Datas { get; set; }

        public event PropertyChangedEventHandler PropertyChanged;
    }
}
