using FLY.FilmCasting.AutoDie.IService;
using GalaSoft.MvvmLight.Command;
using LiveCharts;
using LiveCharts.Configurations;
using System;
using System.ComponentModel;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;

namespace FLY.FilmCasting.AutoDie.UI.Client.UiModule
{
    public class AutoDieGraphVm : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;


        #region 图表控制
        public Func<double, string> YFormatter { get; private set; }
        public int XMax { get; protected set; }
        #endregion

        /// <summary>
        /// 厚度%
        /// </summary>
        public ChartValues<double> ThickPercents { get; } = new ChartValues<double>();
        public ChartValues<int> PreHeats { get; } = new ChartValues<int>();
        public ChartValues<int> Heats { get; } = new ChartValues<int>();
        public ChartValues<int> HeatOffsets { get; } = new ChartValues<int>();

        public ChartValues<bool> Bads { get; } = new ChartValues<bool>();
        public ChartValues<bool> IsStables { get; } = new ChartValues<bool>();
        public object MapperPreHeats { get; private set; }

        [PropertyChanged.DependsOn(nameof(Kp))]
        public object MapperThickPercents { get; private set; }


        [PropertyChanged.DependsOn(nameof(Kp))]
        public object MapperThickPercentsWithIsStable { get; private set; }
        public object Mapper { get; private set; }

        public double Kp { get; protected set; } = 3;
        /// <summary>
        /// 当前选择加热通道
        /// </summary>
        public int SelectBoltNo { get; set; } = -1;
        /// <summary>
        /// 当前选择加热通道数量
        /// </summary>
        public int SelectBoltNoWidth { get; set; } = 0;
        /// <summary>
        /// 长按驱动器
        /// </summary>
        public LongPress LPress { get; } = new LongPress();
        public IFeedbackHeatService FeedbackHeat { get; private set; }

        IFeedbackHeatService mFeedback;
        IHeatBufService mHeatBuf;
        IHeatCellService mHeatCell;
        Button btnClearH;
        protected Brush BadsBrush;
        protected Brush PreHeatsBrush;

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

            var resourceDictionary = new ResourceDictionary() { Source = new Uri("pack://application:,,,/FLY.FilmCasting.AutoDie.UI.Client;component/Themes/Colors.xaml") };
            BadsBrush = resourceDictionary["Brushes.Bad"] as Brush;
            PreHeatsBrush = resourceDictionary["Brushes.PreHeat"] as Brush;

            YFormatter = (y) =>
            {
                string text = y + "%";
                return $"{text,6}";
            };

            MapperPreHeats = Mappers.Xy<int>()
                .X((value, index) =>
                {
                    return index + 1;
                })
                .Y((value, index) =>
                {
                    if (index < Bads.Count() && index >= 0)
                    {
                        if (Bads[index])
                        {
                            if (value == 0)
                                return 100;
                        }
                    }
                    return value;
                })
                .Fill((value, index) =>
                {
                    if (index < Bads.Count() && index >= 0)
                    {
                        if (Bads[index])
                        {
                            return BadsBrush;
                        }
                    }
                    return PreHeatsBrush;
                });
            MapperThickPercents = Mappers.Xy<double>()
                .X((value, index) =>
                {
                    return index + 1;
                })
                .Y((value) =>
                {
                    return value * Kp;
                });

            MapperThickPercentsWithIsStable = Mappers.Xy<double>()
                .X((value, index) =>
                {
                    return index + 1;
                })
                .Y((value, index) =>
                {
                    if (index < IsStables.Count() && index >= 0)
                    {
                        if (!IsStables[index])
                        {
                            return value * Kp;
                        }
                    }
                    return double.NaN;
                });


            Mapper = Mappers.Xy<int>()
                .X((value, index) =>
                {
                    return index + 1;
                })
                .Y((value) =>
                {
                    return value;
                });

            #endregion

            AddCmd = new RelayCommand(Add);
            SubCmd = new RelayCommand(Sub);
            UndoCmd = new RelayCommand(() => mFeedback.Undo());
            CalCmd = new RelayCommand(() => mHeatCell.Cal());
            BaseUpCmd = new RelayCommand(() => mHeatCell.ModifyBase(mFeedback.Step));
            BaseDownCmd = new RelayCommand(() => mHeatCell.ModifyBase(-mFeedback.Step));
            ApplyCmd = new RelayCommand(Apply);
            SaveCmd = new RelayCommand(Save);
            LoadCmd = new RelayCommand(Load);
            EnableCmd = new RelayCommand(EnableAuto);
            CheckCmd = new RelayCommand(Check);
            SmoothCmd = new RelayCommand(() => mHeatCell.Smooth());
            ClearCmd = new RelayCommand(Clear);
        }

        private void Apply()
        {
            SelectBoltNo = -1;
            SelectBoltNoWidth = 0;
            mHeatCell.HeatApply();
        }

        private void Sub()
        {
            for (int i = 0; i < SelectBoltNoWidth; i++)
            {
                int index = SelectBoltNo - 1 + i;
                if (index >= 0 && index < mFeedback.ChannelCnt)
                {
                    mHeatCell.ModifyOffset(index, -mFeedback.Step);
                }
            }
        }

        private void Add()
        {
            for (int i = 0; i < SelectBoltNoWidth; i++)
            {
                int index = SelectBoltNo - 1 + i;
                if (index >= 0 && index < mFeedback.ChannelCnt)
                {
                    mHeatCell.ModifyOffset(index, mFeedback.Step);
                }
            }
        }

        public void Init(
            IFeedbackHeatService feedback,
            IHeatBufService heatBuf,
            IHeatCellService heatCell,
            Button button_clear_h)
        {
            //把 FeedbackHeat 共享。 1个程序，只能有一个 FeedbackHeat
            mFeedback = feedback;
            mHeatBuf = heatBuf;
            mHeatCell = heatCell;

            FeedbackHeat = mFeedback;

            mFeedback.PropertyChanged += mFeedbackHeatService_PropertyChanged;
            mHeatCell.PropertyChanged += MHeatCell_PropertyChanged;
            UpdateAxisX();
            DataBindAll_Thicks();
            DataBindAll_HeatOffsets();
            DataBindAll_Heats();
            DataBindAll_PreHeats();


            Misc.BindingOperations.SetBinding(mHeatCell, nameof(mHeatCell.Kp), this, nameof(Kp));


            this.btnClearH = button_clear_h;
            LPress.Init(btnClearH);
            LPress.LongClick += (s, e) =>
            {
                mHeatCell.ClearPreHeats();
            };

        }

        private void MHeatCell_PropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            if (e.PropertyName == nameof(mHeatCell.ThickPercents))
            {
                DataBindAll_Thicks();

            }
            else if (e.PropertyName == nameof(mHeatCell.Heats))
            {
                DataBindAll_Heats();

            }
            else if (e.PropertyName == nameof(mHeatCell.Offsets))
            {
                DataBindAll_HeatOffsets();

            }
            else if (e.PropertyName == nameof(mHeatCell.PreHeats))
            {
                DataBindAll_PreHeats();
            }
        }

        void mFeedbackHeatService_PropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            if (e.PropertyName == nameof(mFeedback.ChannelCnt))
            {
                UpdateAxisX();
            }
            if (e.PropertyName == nameof(mFeedback.Bads))
            {
                DataBindAll_Bads();
            }
        }


        void DataBindAll_Thicks()
        {
            ThickPercents.Clear();
            if (mHeatCell.ThickPercents != null)
                ThickPercents.AddRange(mHeatCell.ThickPercents);
        }

        void DataBindAll_Heats()
        {
            Heats.Clear();
            if (mHeatCell.Heats != null)
                Heats.AddRange(mHeatCell.Heats);
        }
        void DataBindAll_HeatOffsets()
        {
            HeatOffsets.Clear();
            if (mHeatCell.Offsets != null)
                HeatOffsets.AddRange(mHeatCell.Offsets);
        }
        void DataBindAll_PreHeats()
        {
            PreHeats.Clear();
            if (mHeatCell.PreHeats != null)
                PreHeats.AddRange(mHeatCell.PreHeats);
        }
        void DataBindAll_Bads()
        {
            Bads.Clear();
            if (mFeedback.Bads != null)
                Bads.AddRange(mFeedback.Bads);
            NotifyPropertyChanged(nameof(MapperPreHeats));
        }

        void UpdateAxisX()
        {
            XMax = mFeedback.ChannelCnt + 1;
        }

        public RelayCommand AddCmd { get; }
        public RelayCommand SubCmd { get; }

        public RelayCommand UndoCmd { get; }
        public RelayCommand CalCmd { get; }
        public RelayCommand BaseUpCmd { get; }
        public RelayCommand BaseDownCmd { get; }
        public RelayCommand ApplyCmd { get; }
        public RelayCommand SaveCmd { get; }
        public RelayCommand LoadCmd { get; }
        public RelayCommand EnableCmd { get; }
        public RelayCommand CheckCmd { get; }
        public RelayCommand SmoothCmd { get; }
        public RelayCommand ClearCmd { get; }

        private void Save()
        {
            string productName = mFeedback.HeatsProductName;
            if (!FLY.ControlLibrary.Prompt.Show("请输入产品名称:", ref productName))
                return;

            if (string.IsNullOrEmpty(productName))
            {
                FLY.ControlLibrary.Window_WarningTip.Show("异常",
                    "产品名称 为空",
                    TimeSpan.FromSeconds(2));
                return;
            }
            char[] invalids = System.IO.Path.GetInvalidFileNameChars();

            foreach (char invalidChar in invalids)
            {
                if (productName.Contains(invalidChar))
                {
                    FLY.ControlLibrary.Window_WarningTip.Show("异常",
                        "产品名称 含有非法字符 " + invalidChar,
                        TimeSpan.FromSeconds(2));
                    return;
                }
            }

            if (productName.Length > 30)
            {
                FLY.ControlLibrary.Window_WarningTip.Show("异常",
                    "产品名称 > 30字符",
                    TimeSpan.FromSeconds(2));
                return;
            }

            mFeedback.SaveHeats(productName);
            FLY.ControlLibrary.Window_Tip.Show("加载成功",
                productName,
                TimeSpan.FromSeconds(2));
        }

        private void Load()
        {
            WdLoadHeatsFile w = new WdLoadHeatsFile();
            w.Owner = FLY.ControlLibrary.COMMON.GetWindow(btnClearH);
            w.Init(mFeedback);
            w.ShowDialog();
        }
        private void EnableAuto()
        {
            mFeedback.IsAuto = !mFeedback.IsAuto;
        }
        private void Check()
        {
            mFeedback.CheckEnable = !mFeedback.CheckEnable;
        }


        private void Clear()
        {
            SelectBoltNo = -1;
            SelectBoltNoWidth = 0;
            if (!LPress.IsOK)
                mHeatCell.ClearOffsets();
        }

        protected void NotifyPropertyChanged(string propertyName)
        {
            this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}
