using Aitex.Core.Util;
using LiveCharts.Wpf;
using MECF.Framework.Common.Beckhoff.Station;
using MECF.Framework.Common.CommonData.PUF;
using MECF.Framework.Common.DataCenter;
using MECF.Framework.Common.Equipment;
using MECF.Framework.Common.Layout;
using MECF.Framework.Common.ProcessCell;
using MECF.Framework.Common.Reservior;
using MECF.Framework.Common.Utilities;
using CyberX8_Core;
using CyberX8_Themes.UserControls;
using Prism.Mvvm;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Timers;
using System.Windows.Threading;
using System.Windows;
using System.Windows.Markup;

namespace CyberX8_MainPages.ViewModels
{
    public class ProcessChamberViewModel : BindableBase
    {
        #region 常量
        private const string CURRENT_STATION = "CurrentStation";
        private const string MOTION_DATA = "MotionData";
        /// <summary>
        /// Transporter盒子的宽度85
        /// </summary>
        private const int TRANSPORTER_BOX_LENGTH = 85;
        /// <summary>
        /// Loader Buffer元素宽度的一半(12/2)
        /// </summary>
        private const int LOADER_BUFFER_HALF_LENGTH = 6;
        /// <summary>
        /// Transporter中线最高位置到Cell之间的距离
        /// </summary>
        private const int VERTICAL_DISTANCE = 115;
        #endregion
        #region 内部变量
        private ProcessLayout _processLayout;
        /// <summary>
        /// Loader Gantry运动数据
        /// </summary>
        private CommandMotionData _loaderGantryMotionData;
        /// <summary>
        /// Loader Elevator运动数据
        /// </summary>
        private CommandMotionData _loaderElevatorMotionData;
        /// <summary>
        /// Loader Transporter Gantry当前位置
        /// </summary>
        private double _loaderTransporterGantryPosition;
        /// <summary>
        /// Loader transporter Elevator当前位置
        /// </summary>
        private double _loaderTransporterElevatorPosition;
        /// <summary>
        /// Process Gantry运动数据
        /// </summary>
        private CommandMotionData _processGantryMotionData;
        /// <summary>
        /// Process Elevator运动数据
        /// </summary>
        private CommandMotionData _processElevatorMotionData;
        /// <summary>
        /// Process transporter Gantry当前位置
        /// </summary>
        private double _processTransporterGantryPosition;
        /// <summary>
        /// Process transporter Elevator当前位置
        /// </summary>
        private double _processTransporterElevatorPosition;
        /// <summary>
        /// UI水平距离
        /// </summary>
        private int _transporterLayoutHorizontalDistance;
        /// <summary>
        /// ui 水平比例
        /// </summary>
        private double _horizontalRatio;
        /// <summary>
        /// ui垂直比例
        /// </summary>
        private double _verticalRatio;
        /// <summary>
        /// Loader UI的位置
        /// </summary>
        private int _loaderPosition;
        /// <summary>
        /// Cell 工位最左侧的位置
        /// </summary>
        private double _stationMin;
        /// <summary>
        /// Process与Loader偏差距离
        /// </summary>
        private int _biasDistanceBetweenLoaderAndProcess;
        /// <summary>
        /// RT查询key集合
        /// </summary>
        private List<string> _rtDataKeys = new List<string>();
        /// <summary>
        /// rt查询key数值字典
        /// </summary>
        private Dictionary<string, object> _rtDataValueDic = new Dictionary<string, object>();
        /// <summary>
        /// 定时器
        /// </summary>
        private DispatcherTimer _timer;
        /// <summary>
        /// Process控件是否加载
        /// </summary>
        private bool _processControlLoaded;
        #endregion

        #region 属性
        public ProcessLayout ProcessLayout { get { return _processLayout; } set { SetProperty(ref _processLayout, value); } }
       
        public CommandMotionData LoaderGantryMotionData
        {
            get { return _loaderGantryMotionData; }
            set { SetProperty(ref _loaderGantryMotionData, value); }
        }

        public CommandMotionData LoaderElevatorMotionData
        {
            get { return _loaderElevatorMotionData; }
            set { SetProperty(ref _loaderElevatorMotionData, value); }
        }
        public double LoaderTransporterGantryPosition
        {
            get { return _loaderTransporterGantryPosition; }
            set { SetProperty(ref _loaderTransporterGantryPosition, value); }
        }

        public double LoaderTransporterElevatorPosition
        {
            get { return _loaderTransporterElevatorPosition; }
            set { SetProperty(ref _loaderTransporterElevatorPosition, value); }
        }

        public CommandMotionData ProcessGantryMotionData
        {
            get { return _processGantryMotionData; }
            set { SetProperty(ref _processGantryMotionData, value); }
        }

        public CommandMotionData ProcessElevatorMotionData
        {
            get { return _processElevatorMotionData; }
            set { SetProperty(ref _processElevatorMotionData, value); }
        }

        public double ProcessTransporterGantryPosition
        {
            get { return _processTransporterGantryPosition; }
            set { SetProperty(ref _processTransporterGantryPosition, value); }
        }

        public double ProcessTransporterElevatorPosition
        {
            get { return _processTransporterElevatorPosition; }
            set { SetProperty(ref _processTransporterElevatorPosition, value); }
        }

        public bool ProcessControlLoaded
        {
            get { return _processControlLoaded; }
            set { SetProperty(ref _processControlLoaded, value); }
        }
        #endregion

        public ProcessChamberViewModel()
        {
        }

        /// <summary>
        /// 加载数据
        /// </summary>
        public void LoadData(object obj)
        {
            if (obj==null)
            {
                return;
            }
            ProcessControlLoaded = true;
            _transporterLayoutHorizontalDistance=(int) QueryDataClient.Instance.Service.GetConfig("Transporter.TransporterLayoutHorizontalDistance");
            _loaderPosition = (int)QueryDataClient.Instance.Service.GetConfig("Transporter.TransporterLayoutLoaderPosition");
            _biasDistanceBetweenLoaderAndProcess= (int)QueryDataClient.Instance.Service.GetConfig("Transporter.BiasDistanceBetweenLoaderAndProcess");
            _rtDataKeys.Clear();
            _rtDataKeys.Add($"Station.{ModuleName.Transporter2}.Gantry");
            _rtDataKeys.Add($"Station.{ModuleName.Transporter1}.Gantry");
            _rtDataKeys.Add($"Station.{ModuleName.Transporter2}.Elevator");
            _rtDataKeys.Add($"Station.{ModuleName.Transporter1}.Elevator");
            _rtDataValueDic = QueryDataClient.Instance.Service.PollData(_rtDataKeys);
            if(_rtDataValueDic!=null)
            {
                BeckhoffStationAxis loaderTransporterAxis = CommonFunction.GetValue<BeckhoffStationAxis>(_rtDataValueDic, $"Station.{ModuleName.Transporter2}.Gantry");
                BeckhoffStationAxis processTransporterAxis = CommonFunction.GetValue<BeckhoffStationAxis>(_rtDataValueDic, $"Station.{ModuleName.Transporter1}.Gantry");
                var result = CalculateTransporterMaxMin(loaderTransporterAxis, processTransporterAxis);
                double distance = result.max-_biasDistanceBetweenLoaderAndProcess - result.min;
                _horizontalRatio = distance / _transporterLayoutHorizontalDistance;
                _stationMin = result.min;

                BeckhoffStationAxis loaderTransporterElevatorAxis= CommonFunction.GetValue<BeckhoffStationAxis>(_rtDataValueDic, $"Station.{ModuleName.Transporter2}.Elevator"); 
                BeckhoffStationAxis processTransporterElevatorAxis = CommonFunction.GetValue<BeckhoffStationAxis>(_rtDataValueDic, $"Station.{ModuleName.Transporter1}.Elevator");
                var verticalResult=CalculateTransporterMaxMin(loaderTransporterElevatorAxis, processTransporterElevatorAxis);
                double verticalDistance = verticalResult.max - verticalResult.min;
                _verticalRatio = verticalDistance / VERTICAL_DISTANCE;
            }

            InitialKeys();
            if (_timer == null)
            {
                _timer = new DispatcherTimer();
                _timer.Interval = TimeSpan.FromMilliseconds(100);
                _timer.Tick += Timer_Tick;
            }
            _timer.Start();
        }
        /// <summary>
        /// 隐藏
        /// </summary>
        public void Hide()
        {
            if(_timer!=null)
            {
                _timer.Stop();
            }
        }
        /// <summary>
        /// 定时器执行
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Timer_Tick(object sender, EventArgs e)
        {
            if (_rtDataKeys.Count != 0)
            {
                _rtDataValueDic = QueryDataClient.Instance.Service.PollData(_rtDataKeys);
                if (_rtDataValueDic != null)
                {
                    LoaderGantryMotionData = CommonFunction.GetValue<CommandMotionData>(_rtDataValueDic, $"{ModuleName.Transporter2}.Gantry.{MOTION_DATA}");
                    if (LoaderGantryMotionData != null&&LoaderGantryMotionData.IsDataInitialized)
                    {
                        LoaderTransporterGantryPosition = _loaderPosition + (LoaderGantryMotionData.MotorPosition - _stationMin) / _horizontalRatio - TRANSPORTER_BOX_LENGTH+LOADER_BUFFER_HALF_LENGTH;
                    }

                    LoaderElevatorMotionData= CommonFunction.GetValue<CommandMotionData>(_rtDataValueDic, $"{ModuleName.Transporter2}.Elevator.{MOTION_DATA}");
                    if(LoaderElevatorMotionData!=null&&LoaderElevatorMotionData.IsDataInitialized)
                    {
                        LoaderTransporterElevatorPosition = LoaderElevatorMotionData.MotorPosition / _verticalRatio;
                    }

                    ProcessGantryMotionData = CommonFunction.GetValue<CommandMotionData>(_rtDataValueDic, $"{ModuleName.Transporter1}.Gantry.{MOTION_DATA}");
                    if (ProcessGantryMotionData != null&&ProcessGantryMotionData.IsDataInitialized)
                    {
                        ProcessTransporterGantryPosition =  _loaderPosition+ (ProcessGantryMotionData.MotorPosition+_biasDistanceBetweenLoaderAndProcess - _stationMin) / _horizontalRatio - TRANSPORTER_BOX_LENGTH+LOADER_BUFFER_HALF_LENGTH;
                    }

                    ProcessElevatorMotionData = CommonFunction.GetValue<CommandMotionData>(_rtDataValueDic, $"{ModuleName.Transporter1}.Elevator.{MOTION_DATA}");
                    if (ProcessElevatorMotionData != null && ProcessElevatorMotionData.IsDataInitialized)
                    {
                        ProcessTransporterElevatorPosition = ProcessElevatorMotionData.MotorPosition / _verticalRatio;
                    }

                }
            }
        }

        /// <summary>
        /// 计算Tansporter水平最大值最小值
        /// </summary>
        /// <param name="loaderTransporterAxis"></param>
        /// <param name="processTransporterAxis"></param>
        /// <returns></returns>
        private (double max,double min) CalculateTransporterMaxMin(BeckhoffStationAxis loaderTransporterAxis,BeckhoffStationAxis processTransporterAxis)
        {
            double max = 0;
            double min = double.MaxValue;
            foreach(Station item in loaderTransporterAxis.Stations)
            {
                double position = double.Parse(item.Position);
                if(position > max)
                {
                    max = position;
                }
                if(position<min)
                {
                    min = position;
                }
            }
            foreach (Station item in processTransporterAxis.Stations)
            {
                double position = double.Parse(item.Position);
                if (position > max)
                {
                    max = position;
                }
                if (position < min)
                {
                    min = position;
                }
            }
            return (max,min);
        }
        /// <summary>
        /// 初始化Keys
        /// </summary>
        private void InitialKeys()
        {
            _rtDataKeys.Clear();
            _rtDataKeys.Add($"{ModuleName.Transporter2}.Gantry.{CURRENT_STATION}");
            _rtDataKeys.Add($"{ModuleName.Transporter2}.Gantry.{MOTION_DATA}");
            _rtDataKeys.Add($"{ModuleName.Transporter2}.Elevator.{CURRENT_STATION}");
            _rtDataKeys.Add($"{ModuleName.Transporter2}.Elevator.{MOTION_DATA}");
            _rtDataKeys.Add($"{ModuleName.Transporter1}.Gantry.{CURRENT_STATION}");
            _rtDataKeys.Add($"{ModuleName.Transporter1}.Gantry.{MOTION_DATA}");
            _rtDataKeys.Add($"{ModuleName.Transporter1}.Elevator.{CURRENT_STATION}");
            _rtDataKeys.Add($"{ModuleName.Transporter1}.Elevator.{MOTION_DATA}");
        }
    }
}