using LiveCharts.Configurations;
using NEIntelligentControl2.Models.AGC;
using NEIntelligentControl2.Models.Datas;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.ConstrainedExecution;
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.Navigation;
using System.Windows.Shapes;

namespace NEIntelligentControl2.Views.AGC
{
    /// <summary>
    /// AGC卡片
    /// </summary>
    public partial class AGCCard2 : UserControl
    {
        // ------------依赖属性------------
        public static readonly DependencyProperty StatusProperty = DependencyProperty.Register("Status", typeof(double), typeof(AGCCard2));
        public static readonly DependencyProperty RestrictionValueProperty = DependencyProperty.Register("RestrictionValue", typeof(string), typeof(AGCCard2));
        public static readonly DependencyProperty CurveDeviationRateProperty = DependencyProperty.Register("CurveDeviationRate", typeof(string), typeof(AGCCard2));
        /// <summary>
        /// 状态
        /// </summary>
        public double Status { get => (double)GetValue(StatusProperty); set => SetValue(StatusProperty, value); }
        /// <summary>
        /// 限电值
        /// </summary>
        public string RestrictionValue { get => GetValue(RestrictionValueProperty) as string; set => SetValue(RestrictionValueProperty, value); }
        /// <summary>
        /// 偏差率
        /// </summary>
        public string CurveDeviationRate { get => GetValue(CurveDeviationRateProperty) as string; set => SetValue(CurveDeviationRateProperty, value); }
        private AGCInfo info;
        /// <summary>
        /// 信息
        /// </summary>
        public AGCInfo Info { get => info; set { info = value; InitInfo(); } }

        private ViewModel _ViewModel;

        /// <summary>
        /// 实发有功
        /// </summary>
        private TagInfo _ActualPower;
        private List<TsData> _PowerSetList;
        private List<TsData> _ActualPowerList;
        private List<TsData> _StatusList;
        public AGCCard2()
        {
            InitializeComponent();
            _ViewModel = new ViewModel();
            _pv.Model = _ViewModel;
        }

        /// <summary>
        /// 初始化
        /// </summary>
        private void InitInfo()
        {
            if (info == null)
            {
                return;
            }
            _UGMain.Children.Clear();
            info.Status.ValueChanged = (v) => Status = v;
            foreach (var v in info.AiPoints)
            {
                AGCTag at = new AGCTag() { Info = v };
                _UGMain.Children.Add(at);
            }
            foreach (var v in info.DiPoints)
            {
                AGCTag at = new AGCTag() { Info = v, IsDiPoint = true };
                _UGDiPoint.Children.Add(at);
            }
            var vs = info.AiPoints.Where(ap => ap.Type == TagType.PowerSet || ap.Type == TagType.ActualPower);
            //_PowerTags = vs;
            foreach (var v in vs)
            {
                v.HistoryValueChanged = HistoryValueChanged;
            }
            info.Status.HistoryValueChanged = HistoryValueChanged;

            var rv = info.AiPoints.Where(ap => ap.Type == TagType.PowerSet).FirstOrDefault();
            rv.ValueChanged += PowerSetChanged;
            _ActualPower = info.AiPoints.Where(ap => ap.Type == TagType.ActualPower).FirstOrDefault();
        }

        /// <summary>
        /// 有功设定值改变
        /// </summary>
        private void PowerSetChanged(double obj)
        {
            RestrictionValue = (1 - (obj / info.InstalledCapacity)).ToString("p");
            if (_ActualPower == null || obj == 0) return;
            double cdr = Math.Abs((obj - _ActualPower.Value) / obj);
            CurveDeviationRate = cdr.ToString("p");
            _c.Margin = new Thickness(_pv.ActualModel.PlotArea.Left, 0, 9, 0);

            _cdr.Foreground = cdr > 0.03 ? new SolidColorBrush(Colors.Red) : new SolidColorBrush(Color.FromRgb(0x31, 0xB9, 0xFB));
        }

        /// <summary>
        /// 历史值改变
        /// </summary>
        private void HistoryValueChanged(TagInfo arg1, List<TsData> arg2)
        {
            if (arg2 == null || arg2.Count <= 0) return;
            if (arg1.Type == TagType.Other)
            {
                _StatusList = arg2;
                return;
            }

            _ViewModel.SetValueNow(arg1, arg2);

            _pv.Model = null;
            _pv.Model = _ViewModel;

            if (arg1.Type == TagType.PowerSet)
            {
                _PowerSetList = arg2;
                return;
            }
            else
            {
                _ActualPowerList = arg2;
            }
            if (Status != 1) return;
            InitCurveDeviationRate();
        }

        private void InitCurveDeviationRate()
        {
            if (_PowerSetList == null || _ActualPowerList == null || _StatusList == null) return;
            List<TsData> ls = GetCurveDeviationRateList();

            InitCanvas(ls);
        }

        private void InitCanvas(List<TsData> ls)
        {
            _c.Children.Clear();
            var maxVal = ls.Max(x => x.Value);
            var minTime = ls.Min(x => x.Ts);
            var maxTime = ls.Max(x => x.Ts);
            var totalTime = maxTime - minTime;
            var awidth = _c.ActualWidth;
            var aheight = _c.ActualHeight;
            var width = awidth / ls.Count;
            var ct = Math.Min(ls.Count, _StatusList.Count);
            for (int i = 0; i < ct; ++i)
            {
                var v = ls[i];
                Rectangle r = new Rectangle();
                if (_StatusList[i]?.Value == 0)
                {
                    r.Fill = new SolidColorBrush(Color.FromArgb(0x77, 0x77, 0x77, 0x77));
                }
                else
                {
                    r.Fill = v.Value > 3 ? new SolidColorBrush(Colors.Red) : new SolidColorBrush(Colors.WhiteSmoke);
                }
                r.Width = width;
                r.Height = v.Value * aheight / maxVal;
                var left = awidth * (v.Ts - minTime) / totalTime;
                Canvas.SetLeft(r, left);
                Canvas.SetBottom(r, 0);
                r.ToolTip = Math.Round(v.Value, 2);
                _c.Children.Add(r);
            }
            TextBlock tb = new TextBlock() { Text = Math.Round(maxVal, 2).ToString(), Foreground = new SolidColorBrush(Colors.WhiteSmoke) };
            Canvas.SetRight(tb, 2);
            Canvas.SetTop(tb, 2);
            _c.Children.Add(tb);
        }

        private List<TsData> GetCurveDeviationRateList()
        {
            List<TsData> ls = new List<TsData>();
            int count = Math.Min(_PowerSetList.Count, _ActualPowerList.Count);
            for (int i = 0; i < count; i++)
            {
                double ps = _PowerSetList[i].Value;
                double ap = _ActualPowerList[i].Value;
                double cdr = ps == 0 ? 0 : Math.Abs((ps - ap) / ps) * 100;
                TsData td = new TsData() { Ts = _ActualPowerList[i].Ts, Value = cdr };
                ls.Add(td);
            }
            return ls;
        }

        private void _pv_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            if (e.ClickCount < 1) return;
            Windows.AGCLineWindow.ShowWindow(_ViewModel, info);
        }
    }
}
