using CommunityToolkit.Mvvm.Input;
using FLY.Thick.Base.IService;
using FLY.Thick.Base.UI;
using FLY.Thick.FilmCasting.Common;
using FLY.Thick.FilmCasting.IService;
using FObjBase;
using Misc;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Windows.Controls;
using Unity;
using DynArea = FLY.Thick.Base.Common.DynArea;
using IInitParamService = FLY.Thick.Base.IService.IInitParamService;

namespace FLY.Thick.FilmCasting.UI
{
    /// <summary>
    /// PgProfile.xaml 的交互逻辑
    /// </summary>
    public partial class PgProfile : Page
    {
        PgProfileVm viewModel;
        public PgProfile()
        {
            InitializeComponent();
        }
        [InjectionMethod]
        public void Init(IFilmCastingProfileService profileService, ITDGageService gageService, IBoltMapFilmCastingService boltMapFilmCastingService, IInitParamService initParamService)
        {
            viewModel = new PgProfileVm();
            viewModel.Init(profileService, gageService, boltMapFilmCastingService, initParamService);
            this.DataContext = viewModel;
        }

    }

    public class PgProfileVm : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;

        #region 参数
        public ObservableCollection<string> ProfileList { get; } = new ObservableCollection<string>();
        public FilmCastingProfileParam Param { get; } = new FilmCastingProfileParam();

        public Range DataRange { get; } = new Range();
        public Range ScanRange { get; } = new Range();

        /// <summary>
        /// 自动下辊条件 平均值变化 10um
        /// </summary>
        public double RollDown_AvgChanged { get; set; }
        /// <summary>
        /// 自动下辊条件 膜宽度变化 100mm
        /// </summary>
        public double RollDown_FilmWidthChanged { get; set; }
        /// <summary>
        /// 自动下辊条件 生产长度 大于 10000m
        /// </summary>
        public double RollDown_FilmLength { get; set; }
        /// <summary>
        /// 自动下辊条件 生产时间 2小时
        /// </summary>
        public double RollDown_TimeoutHour { get; set; }
        /// <summary>
        /// 自动下辊条件 停止时间 大于 10min
        /// </summary>
        public double RollDown_StopTimeMin { get; set; }

        /// <summary>
        /// 公差
        /// </summary>
        public double Tolerance { get; set; }
        #endregion

        /// <summary>
        /// 中心螺丝号
        /// </summary>
        public double MidBoltNo { get; set; }
        #region Command
        public RelayCommand ReadCmd { get; private set; }
        public RelayCommand ApplyCmd { get; private set; }
        public RelayCommand ApplyParamCmd { get; private set; }
        public RelayCommand DelCmd { get; private set; }

        public RelayCommand AhelperCmd { get; private set; }
        public RelayCommand SHelperCmd { get; private set; }
        #endregion

        IFilmCastingProfileService profileService;
        IBoltMapFilmCastingService boltMapFilmCastingService;
        IInitParamService initParamService;
        public string SelectedItem { get; set; }

        public DynArea DynArea { get; private set; }
        public IBoltMapFilmCastingService Boltmap => boltMapFilmCastingService;

        public PgProfileVm()
        {
            ReadCmd = new RelayCommand(Read);
            ApplyCmd = new RelayCommand(Apply);
            DelCmd = new RelayCommand(Del);
            AhelperCmd = new RelayCommand(Ahelper);
            ApplyParamCmd = new RelayCommand(ApplyParam);
            SHelperCmd = new RelayCommand(SHelper);
        }



        public void Init(IFilmCastingProfileService profileService, ITDGageService gageService, IBoltMapFilmCastingService boltMapFilmCastingService, IInitParamService initParamService)
        {
            this.DynArea = gageService.DynArea;
            this.profileService = profileService;
            this.boltMapFilmCastingService = boltMapFilmCastingService;
            this.initParamService = initParamService;
            updateParam();
            updateMidBoltNo();

            Misc.BindingOperations.SetBinding(DynArea, nameof(DynArea.IsTest), () =>
            {
                if (DynArea.IsTest)
                {
                    Param.B = 100;
                    Param.K = 1;
                    Param.Target = 100;
                    Param.TolerancePercent = 0.01;
                    Param.PName = "测试模式";
                }
                else
                {
                    Param.B = 0;
                }
            });


            Misc.BindingOperations.SetBinding(profileService, nameof(profileService.RollDown_AvgChanged), this, nameof(RollDown_AvgChanged));
            Misc.BindingOperations.SetBinding(profileService, nameof(profileService.RollDown_FilmWidthChanged), this, nameof(RollDown_FilmWidthChanged));
            Misc.BindingOperations.SetBinding(profileService, nameof(profileService.RollDown_FilmLength), this, nameof(RollDown_FilmLength));
            Misc.BindingOperations.SetBinding(profileService, nameof(profileService.RollDown_TimeoutHour), this, nameof(RollDown_TimeoutHour));
            Misc.BindingOperations.SetBinding(profileService, nameof(profileService.RollDown_StopTimeMin), this, nameof(RollDown_StopTimeMin));


            this.profileService.PropertyChanged += ProfileService_PropertyChanged;



            Tolerance = Math.Round(Param.Target * Param.TolerancePercent, 1);
            Param.PropertyChanged += Param_PropertyChanged_of_Tolerance;
            this.PropertyChanged += PgProfileVm_PropertyChanged_of_Tolerance;

            Param.PropertyChanged += Param_PropertyChanged;
            boltMapFilmCastingService.PropertyChanged += BoltMapFilmCastingService_PropertyChanged;
        }

        private void BoltMapFilmCastingService_PropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            if (e.PropertyName == nameof(boltMapFilmCastingService.BoltCnt))
            {
                updateMidBoltNo();
            }
        }

        private void Param_PropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            if ((e.PropertyName == nameof(Param.LeftEmptyBolts)) ||
                (e.PropertyName == nameof(Param.RightEmptyBolts)))
            {
                updateMidBoltNo();
            }
        }
        void updateMidBoltNo()
        {
            MidBoltNo = (boltMapFilmCastingService.BoltCnt - (Param.LeftEmptyBolts + Param.RightEmptyBolts)) / 2.0 + Param.LeftEmptyBolts;


        }

        bool isShieldToleranceChanged = false;
        private void PgProfileVm_PropertyChanged_of_Tolerance(object sender, PropertyChangedEventArgs e)
        {
            if (isShieldToleranceChanged)
                return;

            if (e.PropertyName == nameof(Tolerance))
            {
                if (Param.Target > 0)
                    Param.TolerancePercent = Math.Round(Tolerance / Param.Target, 3);
            }
        }

        private void Param_PropertyChanged_of_Tolerance(object sender, PropertyChangedEventArgs e)
        {
            if ((e.PropertyName == nameof(Param.TolerancePercent)) || (e.PropertyName == nameof(Param.Target)))
            {
                isShieldToleranceChanged = true;
                Tolerance = Math.Round(Param.Target * Param.TolerancePercent, 1);
                isShieldToleranceChanged = false;
            }
        }

        private void ProfileService_PropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            if (e.PropertyName == nameof(FObjBase.Reflect.Reflect_SeviceClient.IsSynced))
            {
                var client = profileService as FObjBase.Reflect.Reflect_SeviceClient;
                if (client.IsSynced)
                {
                    updateParam();
                }
            }
        }

        void updateParam()
        {
            if (profileService is FObjBase.Reflect.Reflect_SeviceClient)
            {
                var client = profileService as FObjBase.Reflect.Reflect_SeviceClient;
                if (!client.IsSynced)
                    return;
            }

            Param.Copy(this.profileService.Param);
            DataRange.Begin = Param.DataRange.Begin + 1;
            DataRange.End = Param.DataRange.End + 1;

            ScanRange.Begin = Param.ScanRange.Begin + 1;
            ScanRange.End = Param.ScanRange.End + 1;



            this.profileService.GetList(
                new AsyncCBHandler(
                    delegate (object asyncContext, object retData)
                    {
                        List<string> list = (List<string>)retData;
                        ProfileList.Clear();
                        for (int i = 0; i < list.Count(); i++)
                            ProfileList.Add(list[i]);

                        if (ProfileList.Contains(Param.PName))
                        {
                            SelectedItem = Param.PName;
                        }
                    }), null);
        }


        private void Read()
        {
            if (SelectedItem != null)
            {
                string productname = SelectedItem;
                profileService.Read(
                    productname,
                    new AsyncCBHandler(
                    delegate (object AsyncState, object retData)
                    {
                        var p = (FilmCastingProfileParam)retData;
                        Misc.PropertiesManager.CopyTo(p, Param);
                    }), null);
            }
        }

        private void ApplyParam()
        {
            int totalmm = (int)(initParamService.PosLength * initParamService.Encoder1_mmpp);

            if (!Param.IsAutoDataRange)
            {
                if (DataRange.Begin < 1)
                {
                    FLY.ControlLibrary.Window_WarningTip.Show("参数出错", "数据范围.开始 < 1 异常");
                    return;
                }
                if (DataRange.End > boltMapFilmCastingService.BoltCnt)
                {
                    FLY.ControlLibrary.Window_WarningTip.Show("参数出错", $"数据范围.结束 > {boltMapFilmCastingService.BoltCnt},  异常!");
                    return;
                }
                if (DataRange.End <= DataRange.Begin)
                {
                    FLY.ControlLibrary.Window_WarningTip.Show("参数出错", "数据范围.结束<=开始, 异常!");
                    return;
                }
            }
            else
            {
                if (Param.SideCutWidth < 0)
                {
                    FLY.ControlLibrary.Window_WarningTip.Show("参数出错", "切边宽度小于0mm, 异常!");
                    return;
                }


                if (Param.SideCutWidth > totalmm / 3)
                {
                    FLY.ControlLibrary.Window_WarningTip.Show("参数出错", $"切边宽度 大于 总机架长度({totalmm}mm)的 1/3, 异常!");
                    return;
                }
            }

            if (ScanRange.Begin < 1)
            {
                FLY.ControlLibrary.Window_WarningTip.Show("参数出错", "扫描范围.开始 < 1, 异常!");
                return;
            }
            if (ScanRange.End > boltMapFilmCastingService.BoltCnt)
            {
                FLY.ControlLibrary.Window_WarningTip.Show("参数出错", $"扫描范围.结束 > {boltMapFilmCastingService.BoltCnt}, 异常!");
                return;
            }
            if (ScanRange.End <= ScanRange.Begin)
            {
                FLY.ControlLibrary.Window_WarningTip.Show("参数出错", "扫描范围.结束<=开始, 异常!");
                return;
            }

            if (Param.LeftEmptyBolts < 0)
            {
                FLY.ControlLibrary.Window_WarningTip.Show("参数出错", "开始无效螺丝数 < 0, 异常!");
                return;
            }

            if (Param.LeftEmptyBolts > boltMapFilmCastingService.BoltCnt / 3)
            {
                FLY.ControlLibrary.Window_WarningTip.Show("参数出错", $"开始无效螺丝数 > 总螺丝数({boltMapFilmCastingService.BoltCnt})的1/3, 异常!");
                return;
            }

            if (Param.RightEmptyBolts < 0)
            {
                FLY.ControlLibrary.Window_WarningTip.Show("参数出错", "结束无效螺丝数 < 0, 异常!");
                return;
            }

            if (Param.RightEmptyBolts > boltMapFilmCastingService.BoltCnt / 3)
            {
                FLY.ControlLibrary.Window_WarningTip.Show("参数出错", $"结束无效螺丝数 > 总螺丝数({boltMapFilmCastingService.BoltCnt})的1/3, 异常!");
                return;
            }

            if (Param.UniformShrinkPercent > 0.5)
            {
                FLY.ControlLibrary.Window_WarningTip.Show("参数出错", "收缩率 > 50%, 异常!");
                return;
            }


            if (Param.MidOffset > totalmm / 3)
            {
                FLY.ControlLibrary.Window_WarningTip.Show("参数出错", $"中心位置偏移 > 总机架长度({totalmm}mm)的 1/3, 异常!");
                return;
            }

            if (Param.K < 0.1)
            {
                FLY.ControlLibrary.Window_WarningTip.Show("参数出错", $"斜率K 补偿 < 0.1, 异常!");
                return;
            }
            Param.K = Math.Round(Param.K, 3);

            if (Param.Target < 5)
            {
                FLY.ControlLibrary.Window_WarningTip.Show("参数出错", $"目标值 < 5, 异常!");
                return;
            }

            if (Param.TolerancePercent < 0.005)
            {
                FLY.ControlLibrary.Window_WarningTip.Show("参数出错", $"公差 < 0.5%, 异常!");
                return;
            }

            if (string.IsNullOrWhiteSpace(Param.PName))
            {
                FLY.ControlLibrary.Window_WarningTip.Show("参数出错", $"名称 为空, 异常!");
                return;
            }
            if (string.IsNullOrWhiteSpace(Param.Batch))
            {
                FLY.ControlLibrary.Window_WarningTip.Show("参数出错", $"批号 为空, 异常!");
                return;
            }
            if (string.IsNullOrWhiteSpace(Param.Number))
            {
                FLY.ControlLibrary.Window_WarningTip.Show("参数出错", $"卷号 为空, 异常!");
                return;
            }


            if (!Param.IsAutoDataRange)
                Param.DataRange = new RangeStruct(DataRange.Begin - 1, DataRange.End - 1);

            Param.ScanRange = new RangeStruct(ScanRange.Begin - 1, ScanRange.End - 1);


            if (DynArea.IsTest)
            {
                Param.B = 100;
                Param.K = 1;
                Param.Target = 100;
                Param.TolerancePercent = 0.01;
                Param.PName = "测试模式";
            }
            else
            {
                if (Param.Target <= 0)
                {
                    FLY.ControlLibrary.Window_WarningTip.Show("参数出错", "目标值<=0 异常");
                    return;
                }

                if (Param.TolerancePercent <= 0)
                {
                    FLY.ControlLibrary.Window_WarningTip.Show("参数出错", "公差 % <=0 异常");
                    return;
                }
            }


            profileService.ApplyParam(Param);

            if (!ProfileList.Contains(Param.PName))
            {
                ProfileList.Add(Param.PName);
            }
            FLY.ControlLibrary.Window_Tip.Show("应用 & 保存成功",
                Param.PName,
                TimeSpan.FromSeconds(2));

        }

        private void Apply()
        {
            profileService.RollDown_AvgChanged = RollDown_AvgChanged;
            profileService.RollDown_FilmWidthChanged = RollDown_FilmWidthChanged;
            profileService.RollDown_FilmLength = RollDown_FilmLength;
            profileService.RollDown_TimeoutHour = RollDown_TimeoutHour;
            profileService.RollDown_StopTimeMin = RollDown_StopTimeMin;
            profileService.Apply();
            FLY.ControlLibrary.Window_Tip.Show("应用成功",
                "",
                TimeSpan.FromSeconds(2));
        }
        private void Del()
        {
            if (SelectedItem != null)
            {
                string productname = SelectedItem;
                profileService.Del(productname);
                ProfileList.Remove(productname);
                FLY.ControlLibrary.Window_Tip.Show("删除成功",
                    productname,
                    TimeSpan.FromSeconds(2));
            }
        }

        private void Ahelper()
        {
            if (DynArea.IsTest)
            {
                //需要先把测试模式关闭
                FLY.ControlLibrary.Window_WarningTip.Show("操作异常", "需要先把测试模式关闭");
                return;
            }
            WdAHelper w = new WdAHelper();

            w.Init(Param.K);

            w.Owner = App.Current.MainWindow;
            if (w.ShowDialog() == true)
            {
                Param.K = Math.Round(w.A,3);
                Param.B = 0;
            }
        }
        private void SHelper()
        {
            WdShrinkHelper w = new WdShrinkHelper();
            w.Init(boltMapFilmCastingService, Param);
            w.Owner = App.Current.MainWindow;
            w.ShowDialog();
        }
    }
}
