using CommunityToolkit.Mvvm.Input;
using FLY.FilmCasting.AutoDie.Common;
using FLY.FilmCasting.AutoDie.IService;
using FLY.Thick.Base.UI;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using Unity;

namespace FLY.FilmCasting.AutoDie.UI.Client
{
    /// <summary>
    /// Page_Setup.xaml 的交互逻辑
    /// </summary>
    public partial class PgSetup : Page
    {
        PgSetupVm viewModel;
        public PgSetup()
        {
            InitializeComponent();
        }

        [InjectionMethod]
        public void Init(
            IUnityContainer container,
            IFeedbackHeatService feedback,
            IHeatBufService heatBuf,
            IHeatCellService heatCell)
        {
            viewModel = new PgSetupVm();
            viewModel.Init(container, feedback, heatBuf, heatCell);
            this.DataContext = viewModel;
        }

    }

    public class PgSetupVm : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;

        #region 参数
        public double ThresholdHeatSigma { get; set; }
        public int Step { get; set; }
        public bool HasCheckFilmVelocity { get; set; }
        public bool HasCheck { get; set; }
        public int Delay { get; set; }
        public int ThresholdSigmaMax { get; set; }

        public int StableRange { get; set; }
        public int[] HeatEffectCurve { get; set; }
        public bool IsForbidUpDown { get; set; }

        public double CtrlLine { get; set; }
        public double Kp { get; set; }

        /// <summary>
        /// 对位模式, 加热与厚度相关性阀值, 相关性 >=0.7
        /// </summary>
        public double ThresholdR { get; set; }

        /// <summary>
        /// 最大功率
        /// </summary>
        public int MaxHeat { get; set; } = 100;

        /// <summary>
        /// 偏移量界面的显示范围
        /// </summary>
        public int RangeOfOffset { get; set; } = 50;

        /// <summary>
        /// 中心偏厚 单位 %
        /// </summary>
        public double CenterTarget { get; set; }

        /// <summary>
        /// 基础加热 单位 %
        /// </summary>
        public int BaseHeat { get; set; } = 15;

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

        /// <summary>
        /// 膜距离
        /// </summary>
        public double FilmLength { get; set; } = 20;

        /// <summary>
        /// 分级控制
        /// </summary>
        public ObservableCollection<LvCtrlLine> LvCtrlLines { get; } = new ObservableCollection<LvCtrlLine>();
        #endregion

        #region Command
        public RelayCommand SmoothCmd { get; }
        public RelayCommand ApplyCmd { get; }

        #endregion

        public IFeedbackHeatService Feedback { get; private set; }
        public IHeatBufService HeatBuf { get; private set; }
        public IHeatCellService HeatCell { get; private set; }

        IUnityContainer container;
        public PgSetupVm()
        {
            SmoothCmd = new RelayCommand(() =>
            {
                HeatCell.ThresholdHeatSigma = this.ThresholdHeatSigma;
                HeatCell.Smooth();
            });
            ApplyCmd = new RelayCommand(Apply);


        }
        [InjectionMethod]
        public void Init(
            IUnityContainer container,
            IFeedbackHeatService feedback,
            IHeatBufService heatBuf,
            IHeatCellService heatCell)
        {
            this.container = container;
            this.Feedback = feedback;
            this.HeatBuf = heatBuf;
            this.HeatCell = heatCell;

            //参数绑定
            #region 参数
            Misc.BindingOperations.SetBinding(this.HeatCell, nameof(IHeatCellService.ThresholdHeatSigma), this, nameof(ThresholdHeatSigma));
            Misc.BindingOperations.SetBinding(this.HeatCell, nameof(IHeatCellService.IsForbidUpDown), this, nameof(IsForbidUpDown));
            Misc.BindingOperations.SetBinding(this.HeatCell, nameof(IHeatCellService.CtrlLine), this, nameof(CtrlLine));
            Misc.BindingOperations.SetBinding(this.HeatCell, nameof(IHeatCellService.Kp), this, nameof(Kp));
            Misc.BindingOperations.SetBinding(this.HeatCell, nameof(IHeatCellService.MaxHeat), this, nameof(MaxHeat));
            Misc.BindingOperations.SetBinding(this.HeatCell, nameof(IHeatCellService.RangeOfOffset), this, nameof(RangeOfOffset));
            Misc.BindingOperations.SetBinding(this.HeatCell, nameof(IHeatCellService.CenterTarget), this, nameof(CenterTarget));
            Misc.BindingOperations.SetBinding(this.HeatCell, nameof(IHeatCellService.LvCtrlLines), () =>
            {
                LvCtrlLines.Clear();
                if (this.HeatCell.LvCtrlLines == null)
                    return;
                if (this.HeatCell.LvCtrlLines.Count() == 0)
                    return;
                foreach (var lvCtrlLine in this.HeatCell.LvCtrlLines)
                {
                    LvCtrlLines.Add(new LvCtrlLine() { CtrlLine = lvCtrlLine.CtrlLine, Mix = lvCtrlLine.Mix });
                }
            });
            Misc.BindingOperations.SetBinding(this.HeatCell, nameof(IHeatCellService.Mix), this, nameof(Mix));
            Misc.BindingOperations.SetBinding(this.HeatCell, nameof(IHeatCellService.BaseHeat), this, nameof(BaseHeat));



            Misc.BindingOperations.SetBinding(this.Feedback, nameof(IFeedbackHeatService.Step), this, nameof(Step));
            Misc.BindingOperations.SetBinding(this.Feedback, nameof(IFeedbackHeatService.HasCheck), this, nameof(HasCheck));
            Misc.BindingOperations.SetBinding(this.Feedback, nameof(IFeedbackHeatService.Delay), this, nameof(Delay));
            Misc.BindingOperations.SetBinding(this.Feedback, nameof(IFeedbackHeatService.HasCheckFilmVelocity), this, nameof(HasCheckFilmVelocity));
            Misc.BindingOperations.SetBinding(this.Feedback, nameof(IFeedbackHeatService.FilmLength), this, nameof(FilmLength));



            Misc.BindingOperations.SetBinding(this.HeatBuf, nameof(IHeatBufService.ThresholdSigmaMax), this, nameof(ThresholdSigmaMax));
            Misc.BindingOperations.SetBinding(this.HeatBuf, nameof(IHeatBufService.StableRange), this, nameof(StableRange));
            Misc.BindingOperations.SetBinding(this.HeatBuf, nameof(IHeatBufService.HeatEffectCurve), () =>
            {
                if (this.HeatBuf.HeatEffectCurve != null)
                    HeatEffectCurve = (int[])this.HeatBuf.HeatEffectCurve.Clone();
                else
                    HeatEffectCurve = null;
            });
            Misc.BindingOperations.SetBinding(this.HeatBuf, nameof(IHeatBufService.ThresholdR), this, nameof(ThresholdR));




            #endregion
        }

        bool CheckValid_HeatEffectCurve()
        {
            int[] list = HeatEffectCurve;

            if ((list == null) || (list.Count() == 0))
            {
                FLY.ControlLibrary.Window_WarningTip.Show(
                    "参数异常", "加热效果为空", TimeSpan.FromSeconds(2));
                return false;
            }
            int cnt = list.Count();
            if ((int)(cnt / 2) * 2 == cnt)
            {
                FLY.ControlLibrary.Window_WarningTip.Show(
                    "参数异常", "加热效果格式出错,应该如2,5,8,5,2", TimeSpan.FromSeconds(2));
                return false;
            }
            for (int i = 0; i < list.Count() / 2; i++)
            {
                int idx0 = i;
                int idx_0 = list.Count() - 1 - idx0;
                if (list[idx0] != list[idx_0])
                {
                    FLY.ControlLibrary.Window_WarningTip.Show(
                        "参数异常", "加热效果格式出错,应该如2,5,8,5,2", TimeSpan.FromSeconds(2));
                    return false;
                }
                int idx1 = idx0 + 1;
                if (list[idx0] > list[idx1])
                {
                    FLY.ControlLibrary.Window_WarningTip.Show(
                        "参数异常", "加热效果格式出错,应该如2,5,8,5,2", TimeSpan.FromSeconds(2));
                    return false;
                }
            }
            return true;
        }

        bool CheckValid_LvCtrlLines()
        {
            for (int i = 0; i < LvCtrlLines.Count(); i++)
            {
                var lvCtrlLine = LvCtrlLines[i];
                if (lvCtrlLine.CtrlLine >= CtrlLine)
                {
                    FLY.ControlLibrary.Window_WarningTip.Show(
                        "参数异常", "多级控制 的每级控制线 必须小于 基本控制线", TimeSpan.FromSeconds(2));
                    return false;
                }
                if (lvCtrlLine.Mix <= Mix)
                {
                    FLY.ControlLibrary.Window_WarningTip.Show(
                        "参数异常", "多级控制 的每级厚度混合数 必须大于 基本厚度混合数", TimeSpan.FromSeconds(2));
                    return false;
                }

                if (i + 1 < LvCtrlLines.Count())
                {
                    var lvCtrlLine1 = LvCtrlLines[i + 1];

                    if (lvCtrlLine.CtrlLine <= lvCtrlLine1.CtrlLine)
                    {
                        FLY.ControlLibrary.Window_WarningTip.Show(
                            "参数异常", "多级控制 的每级控制线 必须 从大到小排列", TimeSpan.FromSeconds(2));
                        return false;
                    }
                    if (lvCtrlLine.Mix >= lvCtrlLine1.Mix)
                    {
                        FLY.ControlLibrary.Window_WarningTip.Show(
                            "参数异常", "多级控制 的每级混合数 必须 从小到大排列", TimeSpan.FromSeconds(2));
                        return false;
                    }
                }
            }
            return true;
        }

        bool CheckValid()
        {
            if (CheckValid_HeatEffectCurve() == false)
                return false;
            if (CheckValid_LvCtrlLines() == false)
                return false;


            if (Mix < 2)
            {
                FLY.ControlLibrary.Window_WarningTip.Show(
                    "参数异常", "混合数<2", TimeSpan.FromSeconds(2));
                return false;
            }

            if (FilmLength < 2)
            {
                FLY.ControlLibrary.Window_WarningTip.Show(
                    "参数异常", "模头到测厚仪距离<2m", TimeSpan.FromSeconds(2));
                return false;
            }

            if (BaseHeat < 0 || BaseHeat > 50)
            {
                FLY.ControlLibrary.Window_WarningTip.Show(
                    "参数异常", "基础加热不能小于0% 或者大于 50%", TimeSpan.FromSeconds(2));
                return false;
            }


            return true;
        }

        private void Apply()
        {
            if (!WdPassword.Authorize("AutoDie"))
                return;

            if (!CheckValid())
                return;

            //参数设置
            HeatCell.ThresholdHeatSigma = this.ThresholdHeatSigma;
            HeatCell.IsForbidUpDown = this.IsForbidUpDown;
            HeatCell.CtrlLine = Math.Round(this.CtrlLine, 1);
            HeatCell.Kp = this.Kp;
            HeatCell.MaxHeat = this.MaxHeat;
            HeatCell.RangeOfOffset = this.RangeOfOffset;
            HeatCell.CenterTarget = Math.Round(this.CenterTarget, 1);
            HeatCell.BaseHeat = this.BaseHeat;

            if (LvCtrlLines.Count() > 0)
            {
                var lvCtrlLines = new LvCtrlLine[LvCtrlLines.Count()];

                for (int i = 0; i < LvCtrlLines.Count(); i++)
                {
                    var lvCtrlLine = LvCtrlLines[i];
                    lvCtrlLines[i] = new LvCtrlLine() { CtrlLine = lvCtrlLine.CtrlLine, Mix = lvCtrlLine.Mix };
                }
                HeatCell.LvCtrlLines = lvCtrlLines;
            }
            else
            {
                HeatCell.LvCtrlLines = null;
            }
            HeatCell.Mix = Mix;

            Feedback.Step = this.Step;
            Feedback.HasCheckFilmVelocity = this.HasCheckFilmVelocity;
            Feedback.HasCheck = this.HasCheck;
            Feedback.Delay = this.Delay;
            Feedback.FilmLength = FilmLength;





            HeatBuf.ThresholdSigmaMax = this.ThresholdSigmaMax;
            HeatBuf.StableRange = this.StableRange;
            HeatBuf.HeatEffectCurve = this.HeatEffectCurve;
            HeatBuf.ThresholdR = this.ThresholdR;

            HeatCell.Apply();
            HeatBuf.Apply();
            Feedback.Apply();
            FLY.ControlLibrary.Window_Tip.Show("参数设置", "成功", TimeSpan.FromSeconds(2));
        }
    }

    public class PgSetupVmUt : PgSetupVm
    {
        public PgSetupVmUt()
        {
            ThresholdHeatSigma = 7;
            Step = 5;
            HasCheckFilmVelocity = true;
            HasCheck = true;
            Delay = 60;
            ThresholdSigmaMax = 4;
            StableRange = 4;
            HeatEffectCurve = new int[] { 2, 3, 7, 3, 2 };
            IsForbidUpDown = true;
            CtrlLine = 5;
            Kp = 0.8;
            ThresholdR = 0.7;

            MaxHeat = 50;

            RangeOfOffset = 30;

            CenterTarget = 2;

            Mix = 3;
            FilmLength = 12;

            LvCtrlLines.Add(new LvCtrlLine() { CtrlLine = 3, Mix = 6 });
            LvCtrlLines.Add(new LvCtrlLine() { CtrlLine = 1, Mix = 100 });
        }
    }
    public class HeatEffectConverter : IValueConverter
    {
        #region IValueConverter 成员

        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            var list = value as int[];
            if (list == null)
            {
                return null;
            }
            string str = "";
            for (int i = 0; i < list.Count(); i++)
            {
                if (i == 0)
                    str += list[i].ToString();
                else
                    str += "," + list[i].ToString();
            }
            return str;
        }

        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            string str = value as string;
            if (string.IsNullOrEmpty(str))
            {
                //不合法
                return null;
            }
            string[] ss = str.Split(',');
            List<int> list = new List<int>();
            for (int i = 0; i < ss.Length; i++)
            {
                int num;
                if (int.TryParse(ss[i], out num))
                {
                    list.Add(num);
                }
            }
            return list.ToArray();
        }

        #endregion
    }
    public class TimeSpan2SecondConverter : IValueConverter
    {
        #region IValueConverter 成员

        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            if (!(value is TimeSpan))
                return null;


            TimeSpan ts = (TimeSpan)value;
            return (int)(ts.TotalSeconds);
        }

        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            return null;
        }

        #endregion
    }
    public class StableConverter : IValueConverter
    {
        #region IValueConverter 成员

        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            STABILITY stable = (STABILITY)value;
            switch (stable)
            {
                case STABILITY.IDLE:
                    return "等待";
                case STABILITY.ERROR_NO_ARRIVE:
                    return "等待:加热点还没到达测厚仪";
                case STABILITY.ERROR_SIGMA_OVERSIZE:
                    return "等待:2σ太大 ";
                case STABILITY.ERROR_PARAM_CHANGED:
                    return "等待:膜宽变化大于100mm";
                case STABILITY.ERROR_THICK_CHANGED:
                    return "等待:厚度均值波动大";
                case STABILITY.ERROR_CORREL:
                    return "等待:相关性不够";
                case STABILITY.OK_CORREL:
                    return "稳定:相关性高";
                default:
                    return "???";
            }
        }

        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            return null;
        }

        #endregion
    }
    public class MaxR2VisConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            if (!(value is double))
                return null;
            double maxR = (double)value;
            if (maxR < 0)
            {
                return Visibility.Collapsed;
            }
            else
            {
                return Visibility.Visible;
            }
        }

        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }

    public class Id2VisConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            if (!(value is long))
                return null;
            long id = (long)value;
            if (id < 0)
            {
                return Visibility.Collapsed;
            }
            else
            {
                return Visibility.Visible;
            }
        }

        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }

}