using Aitex.Core.RT.DataCenter;
using Aitex.Core.RT.Log;
using Aitex.Core.RT.OperationCenter;
using Aitex.Core.RT.SCCore;
using MECF.Framework.Common.Beckhoff.Station;
using MECF.Framework.Common.DataCenter;
using MECF.Framework.Common.Equipment;
using MECF.Framework.Common.Layout;
using CyberX8_Core;
using CyberX8_RT.Devices.AXIS;
using CyberX8_RT.Devices.AXIS.Yaskawa;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Aitex.Core.RT.Device;
using MECF.Framework.Common.ToolLayout;
using MECF.Framework.Common.Utilities;
using MECF.Framework.Common.WaferHolder;
namespace CyberX8_RT.Devices.TransPorter
{
    public class LoaderTransPorterGantryAxisInterLock : IAxisInterLock
    {
        #region 常量
        private const int TRANSPORTER_BOX_LENGTH = 85;
        #endregion
        #region 内部变量
        private JetAxisBase _axis;
        #endregion
        #region 属性
        /// 
        /// 模块名称
        /// 
        public string Module { get { return _axis.Module; } }
        /// 
        /// 子模块名称
        /// 
        public string Name { get { return _axis.Name; } }
        #endregion
        /// 
        /// 栣函数
        /// 
        /// 
        /// 
        public LoaderTransPorterGantryAxisInterLock(JetAxisBase axis)
        {
            _axis = axis;
            OP.Subscribe($"{Module}.{Name}.{MotionOperation.SaveWithModifyLayout}", SaveWithModifyLayoutOperation);
        }
        /// 
        /// GotoPosition条件检验
        /// 
        /// 
        /// 
        /// 
        public bool CheckGotoPosition(string station)
        {
            if (!AxisManager.Instance.CheckModuleAxisSwitchOn(Module, Name))
            {
                return false;
            }
            JetAxisBase elevatorAxis = DEVICE.GetDevice($"{Module}.Elevator");
            if (elevatorAxis != null)
            {
                if (elevatorAxis.IsRun)
                {
                    LOG.WriteLog(eEvent.ERR_AXIS, Module, "Elevator Axis is Run");
                    return false;
                }
            }
            if (WaferHolderManager.Instance.HasWaferHolder(Module.ToString()))
            {
                double elevatorPosition = elevatorAxis.MotionData.MotorPosition;
                if (elevatorAxis.CheckPositionIsInStation(elevatorPosition, "Up"))
                {
                    return true;
                }
                else
                {
                    LOG.WriteLog(eEvent.ERR_AXIS, Module, $"{Module} has Wafer Shuttle,Elevator {elevatorPosition} is not in Up");
                }
            }
            return true;
        }
        /// 
        /// 保存操作
        /// 
        /// 
        /// 
        /// 
        private bool SaveWithModifyLayoutOperation(string cmd, object[] args)
        {
            string str = $"{Module}.{Name}.{args[0]}";
            bool result = _axis.SaveOperation(cmd, new object[] { str, args[1] });
            if (result)
            {
                string cellId = args[0].ToString();
                string cellName=CellItemManager.Instance.GetModuleNameByCellId(cellId);
                if (!string.IsNullOrEmpty(cellName))
                {
                    ProcessLayoutCellItem item = ProcessLayoutManager.Instance.GetProcessLayoutCellItemByName(cellId);
                    if (item == null)
                    {
                        return true;
                    }
                    int transporterLayoutHorizontalDistance = SC.GetValue("Transporter.TransporterLayoutHorizontalDistance");
                    int loaderPosition = SC.GetValue("Transporter.TransporterLayoutLoaderPosition");
                    int biasDistanceBetweenLoaderAndProcess = SC.GetValue("Transporter.BiasDistanceBetweenLoaderAndProcess");
                    BeckhoffStationAxis loaderTransporterAxis = BeckhoffStationLocationManager.Instance.GetStationAxis(ModuleName.Transporter2.ToString(), "Gantry", 0);
                    BeckhoffStationAxis processTransporterAxis = BeckhoffStationLocationManager.Instance.GetStationAxis(ModuleName.Transporter1.ToString(), "Gantry", 0);
                    var calculateResult = CalculateTransporterHorizontal(loaderTransporterAxis, processTransporterAxis);
                    double distance = calculateResult.max -biasDistanceBetweenLoaderAndProcess - calculateResult.min;
                    double _ratio = distance / transporterLayoutHorizontalDistance;
                    int cellPosition = (int)Math.Round((loaderPosition + (_axis.MotionData.MotorPosition - calculateResult.min) / _ratio), 0);
                    item.Left = cellPosition;
                    if(item.Type=="Cell")
                    {
                        item.Left -= (item.Width/2-5);
                    }
                    try
                    {
                        ProcessLayoutManager.Instance.SaveProcessLayout();
                    }
                    catch (Exception ex)
                    {
                        LOG.WriteLog(eEvent.ERR_TRANSPORTER, Module, $"Save Layout exception {ex.Message}");
                    }
                }
                return true;
            }
            else
            {
                return false;
            }
        }
        /// 
        /// 计算Tansporter水平最大值最小值
        /// 
        /// 
        /// 
        /// 
        private (double max, double min) CalculateTransporterHorizontal(BeckhoffStationAxis loaderTransporterAxis, BeckhoffStationAxis processTransporterAxis)
        {
            double max = 0;
            double min = 0;
            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);
        }
    }
}