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 double XMax { get; protected set; } = double.NaN;
        public double XMin { get; protected set; } = double.NaN;
        #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 => mFeedback;

        FLY.Thick.FilmCasting.Common.FilmCastingProfileParam profileParam;
        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);
        }



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

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

            profileParam.PropertyChanged += ProfileParam_PropertyChanged;


            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 ProfileParam_PropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            if (e.PropertyName == nameof(profileParam.ScanRange))
            {
                UpdateX();
            }
        }
        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))
            {
                UpdateX();
            }
            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 UpdateX()
        {
            if (profileParam.ScanRange.IsValid)
            {
                //数据的X轴，是螺丝号，从1开始
                //profileParam.ScanRange 扫描范围 是序号，从0开始
                //当显示全部螺丝时， 扫描范围 = 0~119  （120个螺丝）
                //XMin = 0， XMax = 121
                XMin = profileParam.ScanRange.Begin;
                XMax = profileParam.ScanRange.End + 2;
            }
            else {
                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();
        }

        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);
                }
            }
        }


        /// <summary>
        /// 设置选择范围。 在ScanMmGraph 中调用
        /// </summary>
        /// <param name="boltNoBegin"></param>
        /// <param name="boltNoEnd"></param>
        public void SetSelected(double boltNoBegin, double boltNoEnd) 
        {
            SelectBoltNo = (int)Math.Min(boltNoBegin,boltNoEnd);

            SelectBoltNoWidth = (int)Math.Abs(boltNoEnd - boltNoBegin) + 1;
        }
        protected void NotifyPropertyChanged(string propertyName)
        {
            this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}
