using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Project
{

    public static partial class Util_Mot
    {
        #region "Common Util"

        //지정한 옵셋범위에 들어있는지 체크합니다.
        static Boolean MatchPosition(double cpos, double tpos, double diff = 0.1)
        {
            var offset = Math.Abs(tpos - cpos);
            return offset <= diff;
        }
        public static double getPositionOffset(eAxis axis, double cmdPos)
        {
            return getPositionOffset((int)axis, cmdPos);
        }
        public static double getPositionOffset(eAxisPXPos point)
        {
            var axis = eAxis.X_PICKER;
            var pos = GetAxPXPos(point);
            return getPositionOffset(axis, pos.position);
        }
        public static double getPositionOffset(eAxisPZPos point)
        {
            var axis = eAxis.Z_PICKER;
            var pos = GetAxPZPos(point);
            return getPositionOffset(axis, pos.position);
        }
        public static double getPositionOffset(eAxisPLMovePos point)
        {
            var axis = eAxis.PL_MOVE;
            var pos = GetAxPLMPos(point);
            return getPositionOffset(axis, pos.position);
        }
        public static double getPositionOffset(eAxisPRMovePos point)
        {
            var axis = eAxis.PR_MOVE;
            var pos = GetAxPRMPos(point);
            return getPositionOffset(axis, pos.position);
        }
        public static double getPositionOffset(eAxisPLUPDNPos point)
        {
            var axis = eAxis.PL_UPDN;
            var pos = GetAxPLZPos(point);
            return getPositionOffset(axis, pos.position);
        }
        public static double getPositionOffset(eAxisPRUPDNPos point)
        {
            var axis = eAxis.PR_UPDN;
            var pos = GetAxPRZPos(point);
            return getPositionOffset(axis, pos.position);
        }

        /// <summary>
        /// 현재위치에서 지정된 위치를 뺀 값입니다. +가 반환되면 현재 위치가 지정위치보다 멀리 있다는 뜻입니다.
        /// </summary>
        /// <param name="axis"></param>
        /// <param name="cmdPos"></param>
        /// <returns></returns>
        public static double getPositionOffset(int axis, double cmdPos)
        {
            var coffset = (Pub.mot.dACTPOS[(int)axis] - cmdPos);
            return coffset;// return coffset < offset;
        }

        public static bool getPositionMatch(eAxis axis, double cmdPos, double offset = 0.1)
        {
            return getPositionMatch((int)axis, cmdPos, offset);
        }

        public static bool getPositionMatch(int axis, double cmdPos, double offset = 0.1)
        {
            var coffset = Math.Abs(Pub.mot.dACTPOS[(int)axis] - cmdPos);
            return coffset < offset;
        }

        public static List<string> GetActiveLockList(eAxis axis, CInterLock Lck)
        {
            var locklist = new List<string>();

            if (Lck.Value > 0)
            {
                for (int i = 0; i < 64; i++)
                {
                    if (Lck.get(i))
                    {
                        var vStr = $"[{i}]";
                        if (axis == eAxis.X_PICKER) vStr = ((eILockPKX)i).ToString();
                        else if (axis == eAxis.Z_PICKER) vStr = ((eILockPKZ)i).ToString();
                        else if (axis == eAxis.Z_THETA) vStr = ((eILockPKT)i).ToString();
                        else if (axis == eAxis.PL_MOVE) vStr = ((eILockPRM)i).ToString();
                        else if (axis == eAxis.PL_UPDN) vStr = ((eILockPRZ)i).ToString();
                        else if (axis == eAxis.PR_MOVE) vStr = ((eILockPRM)i).ToString();
                        else if (axis == eAxis.PR_UPDN) vStr = ((eILockPRZ)i).ToString();
                        locklist.Add(vStr);
                    }
                }
            }
            return locklist;
        }

        public static Boolean Home(string reason, eAxis axis_, Boolean useValidcheck = true)
        {
            string Message;
            int axis = (int)axis_;
            if (useValidcheck == true && !Home_Validation(axis_, out Message))
            {
                Pub.mot.RaiseMessage(string.Format("[{0}-Axis] Move Error : {1}", axis, Message), true);
                return false;
            }

            var HomespdH = new double[] {
                Pub.system.HSpeed0H, Pub.system.HSpeed1H, Pub.system.HSpeed2H,
                Pub.system.HSpeed3H, Pub.system.HSpeed4H, Pub.system.HSpeed5H,
                Pub.system.HSpeed6H,Pub.system.HSpeed7H
            };
            var HomespdL = new double[] {
                Pub.system.HSpeed0L, Pub.system.HSpeed1L, Pub.system.HSpeed2L,
                Pub.system.HSpeed3L, Pub.system.HSpeed4L, Pub.system.HSpeed5L,
                Pub.system.HSpeed6L, Pub.system.HSpeed7L
            };
            var homespdA = new double[] {
                Pub.system.HAcc0, Pub.system.HAcc1, Pub.system.HAcc2,
                Pub.system.HAcc3, Pub.system.HAcc4, Pub.system.HAcc5,
                Pub.system.HAcc6,Pub.system.HAcc7
            };

            var disable_org = new Boolean[] {
                Pub.system.axis0_disable_orgsensor, Pub.system.axis1_disable_orgsensor,Pub.system.axis2_disable_orgsensor,
                Pub.system.axis3_disable_orgsensor, Pub.system.axis4_disable_orgsensor,Pub.system.axis5_disable_orgsensor,
                Pub.system.axis6_disable_orgsensor,Pub.system.axis7_disable_orgsensor
            };

            //Pub.mot.Home(1, arDev.AzinAxt.eMotionDirection.Negative, arDev.AzinAxt.eSoftLimitStopMode.SStop, Pub.setting.HZSpeed, Pub.setting.HZAcc);
            Boolean useOrgSensor = !disable_org[axis]; // (axis_ != eAxis.Marking); //A센서는 ORG가 없으므로 NE센서만으로 처리해야 함
            return Pub.mot.Home(reason, (short)axis, arDev.AzinAxt.eMotionDirection.Negative,
                arDev.AzinAxt.eSoftLimitStopMode.EStop,
                HomespdH[axis],
                HomespdL[axis],
                homespdA[axis],
                useOrgSensor);
        }


        private static DateTime[] MotCmdtime = new DateTime[] { DateTime.Now, DateTime.Now, DateTime.Now, DateTime.Now, DateTime.Now, DateTime.Now, DateTime.Now, DateTime.Now };
        private static double[] MotCmdPos = new double[] { 0, 0, 0, 0, 0, 0, 0, 0 };

        public static Boolean Move(eAxis axis, double pos_mm, double speed, double acc = 1000, Boolean relative = false, Boolean validchk = true, Boolean UserInterLock = true)
        {

            //너무빠른시간 동작하지 못하게 한다
            if (MotCmdPos[(int)axis] == pos_mm)
            {
                var ts = DateTime.Now - MotCmdtime[(int)axis];
                if (ts.TotalMilliseconds < 1000)
                {
                    //너무 빠르게 재시도하지 않게 한다 210115
                    Console.WriteLine("mot command skip : " + axis.ToString() + "pos:" + pos_mm.ToString() + " too short");
                    MotCmdtime[(int)axis] = DateTime.Now.AddMilliseconds(-1500);
                    return true;
                }
                else
                {
                    MotCmdtime[(int)axis] = DateTime.Now;
                    MotCmdPos[(int)axis] = pos_mm;
                }
            }
            else
            {
                MotCmdtime[(int)axis] = DateTime.Now;
                MotCmdPos[(int)axis] = pos_mm;
            }

            //웨이퍼가 감지되는 상태일때 OPEN 되어있다면 이동하지 못하게 한다
            string Message;
            if (validchk == true)
            {
                if (!Move_Validation(axis, out Message))
                {
                    Pub.log.AddE(string.Format("[{0}-Axis] Move Error : {1}", axis, Message));
                    //Pub.mot.RaiseMessage(, true);
                    return false;
                }
            }

            //해당 축 ILOCK체크
            if (UserInterLock)
            {
                //lock이 걸린경우 lock 걸린 항목을 모두 확인하면 좋다
                if (axis == eAxis.X_PICKER && Pub.LockPKX.Value > 0)
                {
                    var locklist = Util_Mot.GetActiveLockList(axis, Pub.LockPKX);
                    Pub.mot.errorMessage = "X_PICKER Interlock(" + string.Join(",", locklist) + ")";
                    return false;
                }
                else if (axis == eAxis.Z_PICKER && Pub.LockPKZ.Value > 0)
                {
                    var locklist = Util_Mot.GetActiveLockList(axis, Pub.LockPKZ);
                    Pub.mot.errorMessage = "Z_PICKER Interlock(" + string.Join(",", locklist) + ")";
                    return false;
                }
                else if (axis == eAxis.Z_THETA && Pub.LockPKT.Value > 0)
                {
                    var locklist = Util_Mot.GetActiveLockList(axis, Pub.LockPKT);
                    Pub.mot.errorMessage = "Z_THETA Interlock(" + string.Join(",", locklist) + ")";
                    return false;
                }
                else if (axis == eAxis.PL_MOVE && Pub.LockPLM.Value > 0)
                {
                    var locklist = Util_Mot.GetActiveLockList(axis, Pub.LockPLM);
                    Pub.mot.errorMessage = "PL_MOVE Interlock(" + string.Join(",", locklist) + ")";
                    return false;
                }
                else if (axis == eAxis.PL_UPDN && Pub.LockPLZ.Value > 0)
                {
                    var locklist = Util_Mot.GetActiveLockList(axis, Pub.LockPLZ);
                    Pub.mot.errorMessage = "PL_UPDN Interlock(" + string.Join(",", locklist) + ")";
                    return false;
                }
                else if (axis == eAxis.PR_MOVE && Pub.LockPRM.Value > 0)
                {
                    var locklist = Util_Mot.GetActiveLockList(axis, Pub.LockPRM);
                    Pub.mot.errorMessage = "PR_MOVE Interlock(" + string.Join(",", locklist) + ")";
                    return false;
                }
                else if (axis == eAxis.PR_UPDN && Pub.LockPRZ.Value > 0)
                {
                    var locklist = Util_Mot.GetActiveLockList(axis, Pub.LockPRZ);
                    Pub.mot.errorMessage = "PR_UPDN Interlock(" + string.Join(",", locklist) + ")";
                    return false;
                }
            }

            var pos_pulse = pos_mm;// *10;
            var result = Pub.mot.Move((short)axis, pos_pulse, speed, acc, acc, relative, false, validchk);
            if (!result) Pub.mot.RaiseMessage("Move(X) Error : " + Pub.mot.errorMessage, true);
            return result;
        }


        #endregion
    }
}
