using FLY.Thick.FilmCasting.IService;
using LiveCharts;
using LiveCharts.Configurations;
using Misc;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Windows.Media;

namespace FLY.Thick.FilmCasting.UI.UiModule
{
    public class TrendGraphVmUt : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;

        #region 图表控制
        public double YMax { get; set; } = double.NaN;
        public double YMin { get; set; } = double.NaN;
        public double ToleranceYMax { get; set; } = double.NaN;
        public double ToleranceYMin { get; set; } = double.NaN;
        public double Tolerance2YMax { get; set; } = double.NaN;
        public double Tolerance2YMin { get; set; } = double.NaN;

        public double XMax { get; set; } = double.NaN;
        public Func<double, string> YFormatter { get; private set; }
        public Func<double, string> XFormatter { get; private set; }
        #endregion

        #region 界面统计值

        /// <summary>
        /// 平均值
        /// </summary>
        public double Average { get; private set; } = double.NaN;

        /// <summary>
        /// 最大值
        /// </summary>
        public double Max { get; private set; } = double.NaN;

        /// <summary>
        /// 最小值
        /// </summary>
        public double Min { get; private set; } = double.NaN;

        /// <summary>
        /// 混合数
        /// </summary>
        public int Mix { get; private set; } = 2;

        /// <summary>
        /// Values.First().Time
        /// </summary>
        public DateTime BeginTime { get; private set; }
        /// <summary>
        /// Values.Last().Time
        /// </summary>
        public DateTime EndTime { get; private set; }

        /// <summary>
        /// Values.Last().Id
        /// </summary>
        public long Id { get; private set; } = 1231221;

        #endregion

        #region 查询模式
        /// <summary>
        /// 只要 Number被改变,且不为0, AutoKeepNewestTimeRemaining就会被设为10s.
        /// 当 AutoKeepNewestTimeRemaining = 0, Number就会被设置为0
        /// </summary>
        public int AutoKeepNewestTimeRemaining { get; private set; }

        /// <summary>
        /// 当前就是最新的视图
        /// </summary>
        public bool IsNewest { get; private set; }

        /// <summary>
        /// 视图加载中
        /// </summary>
        public bool IsLoading { get; private set; }


        #endregion

        List<Brush> AreaColors;

        public ChartValues<TrendValue> Values { get; } = new ChartValues<TrendValue>();

        public object MapperPositive { get; private set; }
        public object MapperNegative { get; private set; }
        public object MapperValue { get; private set; }

        public TrendGraphVmUt()
        {
            #region 与数据无关界面参数


            AreaColors = new List<Brush>();
            AreaColors.AddRange(FLY.ControlLibrary.Themes.Styles.AreaColors);

            YFormatter = (y) =>
            {
                double percent = y * 100;
                string text = "";
                if (percent == 0d)
                {
                    text = "0.0%";
                }
                else if (percent > 0)
                {
                    text = $"+{Math.Abs(percent):F1}%";
                }
                else
                {
                    text = $"-{Math.Abs(percent):F1}%";
                }
                return $"{text,6}";
            };
            XFormatter = (x) =>
            {
                int index = (int)x;
                if (index < Values.Count() && index >= 0)
                    return Values[index].Time.ToString("HH:mm");
                else
                    return "";
            };

            MapperPositive = Mappers.Xy<TrendValue>()
                .X((value, index) =>
                {
                    return index;
                })
                .Y(value => value.Sigma / value.Value)
                .Fill((value) =>
                {
                    double percent = value.Sigma / value.Value;
                    if ((percent > Tolerance2YMax) || (percent < -Tolerance2YMax))
                    {
                        return AreaColors[0];
                    }
                    else if ((percent > ToleranceYMax) || (percent < -ToleranceYMax))
                    {
                        return AreaColors[1];
                    }
                    else
                    {
                        return AreaColors[2];
                    }
                });

            MapperNegative = Mappers.Xy<TrendValue>()
                .X((value, index) =>
                {
                    return index;
                })
                .Y(value => -value.Sigma / value.Value)
                .Fill((value) =>
                {
                    double percent = value.Sigma / value.Value;
                    if ((percent > Tolerance2YMax) || (percent < -Tolerance2YMax))
                    {
                        return AreaColors[0];
                    }
                    else if ((percent > ToleranceYMax) || (percent < -ToleranceYMax))
                    {
                        return AreaColors[1];
                    }
                    else
                    {
                        return AreaColors[2];
                    }
                });

            MapperValue = Mappers.Xy<TrendValue>()
                .X((value, index) =>
                {
                    return index;
                })
                .Y(value => value.Value);

            #endregion

            Values.Clear();

            #region 数据
            double target = 150;

            double tolerancePercent = 0.05;
            double yRangePercent = 3;
            int len = 200;
            DateTime startTime = DateTime.Now;
            TimeSpan tsInterval = TimeSpan.FromSeconds(30);
            DateTime time = startTime;
            int id = 312456;
            Random random = new Random();
            for (int i = 0; i < len; i++, time += tsInterval)
            {
                TrendValue tv = new TrendValue();
                tv.Time = time;
                tv.Value = target + (random.NextDouble() - 0.5) * target * tolerancePercent * 0.5;
                tv.Sigma = (Math.Sin(i * Math.PI / len) * 3) * target * tolerancePercent * random.NextDouble();

                Values.Add(tv);
            }


            #endregion

            #region 界面数据
            XMax = len;
            Mix = 2;
            BeginTime = Values.First().Time;
            EndTime = Values.Last().Time;
            Id = id;
            var sigma2Percent = Values.Select(v => 2 * v.Sigma / v.Value);
            Average = sigma2Percent.AverageNoNull();
            Max = sigma2Percent.Max();
            Min = sigma2Percent.Min();

            ToleranceYMax = tolerancePercent;
            ToleranceYMin = -ToleranceYMax;
            Tolerance2YMax = ToleranceYMax * 2;
            Tolerance2YMin = -Tolerance2YMax;
            YMax = ToleranceYMax * yRangePercent;
            YMin = -YMax;

            #endregion
        }
    }
}
