using LiveCharts;
using LiveCharts.Configurations;
using LiveCharts.Defaults;
using LiveCharts.Wpf;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using System.Windows.Threading;

namespace WpfApp1
{
    /// <summary>
    /// Window1.xaml 的交互逻辑
    /// </summary>
    public partial class ColumnRangeExample : Window
    {
        ColumnRangeExampleViewModel viewModel;
        public ColumnRangeExample()
        {
            InitializeComponent();
            viewModel = new ColumnRangeExampleViewModel();
            viewModel.Init();
            this.DataContext = viewModel;
        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            if (viewModel.IsRunning)
                viewModel.Stop();
            else
                viewModel.Start();
        }

        private void ButtonGC_Click(object sender, RoutedEventArgs e)
        {
            GC.Collect();
        }


        private void ButtonClear_Click(object sender, RoutedEventArgs e)
        {
            viewModel.BoltValues.Clear();
        }
    }
    public class ColumnRangeExampleViewModel : INotifyPropertyChanged
    {
        DispatcherTimer timer;


        public SeriesCollection SeriesCollection { get; set; }
        public Func<double, string> Formatter { get; set; }

        public double XMin { get; set; } = double.NaN;
        public double XMax { get; set; } = double.NaN;
        public bool IsRunning { get; private set; }
        List<double> datas = new List<double>();
        List<Bolt> boltmap = new List<Bolt>();

        public ChartValues<BoltValue> BoltValues = new ChartValues<BoltValue>();
        public ChartValues<double> Values = new ChartValues<double>();

        

        public void Update()
        {

            Random random = new Random();
            double[] datas2 = new double[datas.Count()];
            for (int i = 0; i < datas.Count(); i++)
            {
                datas2[i] = datas[i] + (random.NextDouble() - 0.5) * 1;
            }
            //把其中一部分数据变为无效
            int null_value_pos = random.Next(1000);
            for (int i = 0; i < 100; i++)
            {
                int index = null_value_pos - 50 + i;
                if (index < 0)
                    index += datas2.Count();
                else if (index >= datas2.Count())
                    index -= datas2.Count();

                datas2[index] = double.NaN;
            }
            //-----------------------------------------------------------
            //转显示数据
            List<BoltValue> boltValues = new List<BoltValue>();
            foreach (Bolt bolt in boltmap)
            {
                IEnumerable<double> a = datas2.Skip(bolt.Begin - 1).Take(bolt.End - bolt.Begin + 1);

                a = from d in a where !double.IsNaN(d) select d;
                double v;
                if (a.Count() > 0)
                    v = a.Average();
                else
                    v = double.NaN;
                boltValues.Add(new BoltValue(bolt.Begin, bolt.End, v));
            }



           // if (SeriesCollection.Count() > 0)
           //     SeriesCollection.Clear();


            BoltValues.Clear();
            Values.Clear();

            BoltValues.AddRange(boltValues);
            Values.AddRange(datas2);




        }
        public void Init()
        {
            //-----------------------------------------------------------
            //模拟数据
            double target = 150;
            double tolerance = 2;

            Random random = new Random();
            for (int i = 0; i < 1000; i++)
            {
                double d = Math.Sin(Math.PI * 2 * i / 350) * tolerance + (random.NextDouble() - 0.5) * 0.3 + target;
                datas.Add(d);
            }


            //平均分为8份
            double width = datas.Count() / 23;
            int begin = 0;
            while (true)
            {
                int end = (int)(begin + width);
                if (end >= datas.Count())
                    end = datas.Count() - 1;
                boltmap.Add(new Bolt(begin, end));
                if (end == datas.Count()-1)
                    break;
                begin = end;
            }
            boltmap[2].End = (boltmap[3].End + boltmap[3].Begin) / 2;

            SeriesCollection = new SeriesCollection();


            SeriesCollection.Add(
new ColumnRangeSeries
{
Title = "ColumnRange",
Values = BoltValues,
StrokeThickness = 2,
Stroke = new SolidColorBrush(System.Windows.Media.Colors.DarkRed),
Fill = new SolidColorBrush(System.Windows.Media.Color.FromArgb(0x80, 0xff, 0, 0)),
DataLabels = true,
YAxisCrossing = 150,
Configuration = Mappers.Weighted<BoltValue>()
.X(b => (b.From + b.To) / 2)
.Weight(b => Math.Abs(b.From - b.To))
.Y(b => b.Value)
});


            Formatter = value => value.ToString("N");
            XMin = 100;
            XMax = 900;

            //-----------------------------------------------------------
            //转显示数据
            Update();

            timer = new DispatcherTimer();
            timer.Interval = TimeSpan.FromSeconds(0.1);
            timer.Tick += Timer_Tick;
        }
        public void Start()
        {
            IsRunning = true;
            timer.Start();
        }
        public void Stop()
        {
            IsRunning = false;
            timer.Stop();
        }
        
        private void Timer_Tick(object sender, EventArgs e)
        {
            Update();
        }

        public event PropertyChangedEventHandler PropertyChanged;
    }
    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
    {
        public int Begin;
        public int End;
        public Bolt(int b, int e)
        {
            Begin = b;
            End = e;
        }
    }
}
