using FLY.Thick.Base.Common;
using FLY.Thick.Base.IService;
using FLY.Thick.Base.UI;
using FLY.Thick.FilmCasting.Common;
using FLY.Thick.FilmCasting.IService;
using FObjBase;
using GalaSoft.MvvmLight.Command;
using Misc;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
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;
using Unity;

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)
        {
            viewModel = new PgProfileVm();
            viewModel.Init(profileService, gageService, boltMapFilmCastingService);
            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

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

        #endregion

        IFilmCastingProfileService profileService;
        IBoltMapFilmCastingService boltMapFilmCastingService;

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



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

            updateParam();

            

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

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

            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 = w.A;
                Param.B = 0;
            }
        }
    }
}
