using cszmcaux;
//using LogClass;
using System;
using System.Collections.Generic;
using System.IO.Ports;
using System.Linq;
using System.Runtime.InteropServices;
using System.Runtime.Remoting.Contexts;
using System.Text;
using System.Threading.Tasks;

namespace CCDCount.DLL
{
    public class ZmcauxClass
    {
        public IntPtr g_handle;         //链接返回的句柄，可以作为卡号
        ConnectContext cc;
        public ZmcauxClass()
        {
            cc = new ConnectContext("LOCAL");
            //cc = new ConnectContext("PCI");
        }

        /// <summary>
        /// 打开轴卡
        /// </summary>
        public bool OpenZmcauxCard()
        {
            bool result = false;
            string Buffer;
            //Buffer = "PCI1";
            Buffer = "LOCAL1";

            int iresult = cc.OpenConnect(ref g_handle, Buffer);

            if (iresult != 0)
            {
                g_handle = (IntPtr)0;
                result = false;
                //LOG.log("轴卡连接失败");
                Console.WriteLine("轴卡连接失败:", iresult);
                //MessageBox.Show("链接失败");
                //this.Text = "未连接";
                return result;
            }
            else
            {
                result = true;
                //LOG.log("轴卡已连接");
                Console.WriteLine("轴卡已连接");
                return result;
            }
        }

        /// <summary>
        /// 关闭轴卡
        /// </summary>
        public void CloseZmcauxCard()
        {
            cc.CloseConnect(g_handle);
            g_handle = (IntPtr)0;
            //LOG.log("轴卡已断开");
            Console.WriteLine("轴卡已断开");
        }

        /// <summary>
        /// 设置轴卡变量
        /// </summary>
        /// <param name="varName">变量名</param>
        /// <param name="cmd">变量值</param>
        public int SetMessageTovar(string varName, float cmd)
        {
            int result = -1;
            if (g_handle != (IntPtr)0)
            {
                result = zmcaux.ZAux_Direct_SetUserVar(g_handle, varName, cmd);
            }
            return result;
        }

        /// <summary>
        /// 设置轴卡数组变量
        /// </summary>
        /// <param name="ArrayName">数组名</param>
        /// <param name="array">传入数组</param>
        /// <param name="start">传入起始点</param>
        /// <param name="length">传入数量</param>
        public void SetMessageToArray(string ArrayName, float[] array, int start, int length)
        {
            if (g_handle != (IntPtr)0)
            {
                zmcaux.ZAux_Direct_SetUserArray(g_handle, ArrayName, start, length, array);
            }
        }

        /// <summary>
        /// 读取轴卡变量
        /// </summary>
        /// <param name="ArrayName"></param>
        /// <param name="cmd"></param>
        public int GetMessageFromVar(string VarName, ref float cmd)
        {
            int result = -1;
            if (g_handle != (IntPtr)0)
            {
                result = zmcaux.ZAux_Direct_GetUserVar(g_handle, VarName, ref cmd);
            }
            return result;
        }

        /// <summary>
        /// 读取轴卡数组变量
        /// </summary>
        /// <param name="ArrayName"></param>
        /// <param name="array"></param>
        /// <param name="start"></param>
        /// <param name="length"></param>
        public void GetMessageFromArray(string ArrayName, ref float[] array, int start, int length)
        {
            if (g_handle != (IntPtr)0)
            {
                zmcaux.ZAux_Direct_GetUserArray(g_handle, ArrayName, start, length, array);
            }
        }

        /// <summary>
        /// 设置输出IO状态
        /// </summary>
        /// <param name="IOStata"></param>
        /// <param name="IOIndex"></param>
        public void SetIOState(bool IOStata, int IOIndex)
        {
            if (g_handle == (IntPtr)0)
            {
                Console.WriteLine("未链接到控制器!", "提示");
                return;
            }

            if (IOStata)
            {
                zmcaux.ZAux_Direct_SetOp(g_handle, IOIndex, 1);
                Console.WriteLine("out{0} 打开", IOIndex);
            }
            else
            {
                zmcaux.ZAux_Direct_SetOp(g_handle, IOIndex, 0);
                Console.WriteLine("out{0} 关闭", IOIndex);
            }
        }

        /// <summary>
        /// 设置轴类型
        /// </summary>
        /// <param name="nAxis">轴号</param>
        /// <param name="Atype">轴类型</param>
        public void SetDirectAtype(int nAxis, int Atype)
        {
            if (g_handle == (IntPtr)0)
            {
                Console.WriteLine("未链接到控制器!", "提示");
                return;
            }
            zmcaux.ZAux_Direct_SetAtype(g_handle, nAxis, 1);
        }

        /// <summary>
        /// 设置轴脉冲当量
        /// </summary>
        /// <param name="nAxis">轴号</param>
        /// <param name="Units">脉冲当量</param>
        public void SetDirectUnits(int nAxis, float Units)
        {
            if (g_handle == (IntPtr)0)
            {
                Console.WriteLine("未链接到控制器!", "提示");
                return;
            }
            zmcaux.ZAux_Direct_SetUnits(g_handle, nAxis, Units);
        }

        public void SetDirectLspeed(int nAxis, float Lspeed)
        {
            if (g_handle == (IntPtr)0)
            {
                Console.WriteLine("未链接到控制器!", "提示");
                return;
            }
            zmcaux.ZAux_Direct_SetLspeed(g_handle, nAxis, Lspeed);
        }

        /// <summary>
        /// 设置轴的运行速度
        /// </summary>
        /// <param name="nAxis">轴号</param>
        /// <param name="speed">运动速度值</param>
        public void SetDirectSpeed(int nAxis, float speed)
        {
            if (g_handle == (IntPtr)0)
            {
                Console.WriteLine("未链接到控制器!", "提示");
                return;
            }
            zmcaux.ZAux_Direct_SetSpeed(g_handle, nAxis, speed);
        }

        /// <summary>
        /// 设置轴加速度
        /// </summary>
        /// <param name="nAxis">轴号</param>
        /// <param name="accel">加速度值</param>
        public void SetDirectAccel(int nAxis, float accel)
        {
            if (g_handle == (IntPtr)0)
            {
                Console.WriteLine("未链接到控制器!", "提示");
                return;
            }
            zmcaux.ZAux_Direct_SetAccel(g_handle, nAxis, accel);
        }

        /// <summary>
        /// 设置轴减速度
        /// </summary>
        /// <param name="nAxis">轴号</param>
        /// <param name="decel">减速度值</param>
        public void SetDirectDecel(int nAxis, float decel)
        {
            if (g_handle == (IntPtr)0)
            {
                Console.WriteLine("未链接到控制器!", "提示");
                return;
            }
            zmcaux.ZAux_Direct_SetDecel(g_handle, nAxis, decel);
        }

        /// <summary>
        /// 设置轴S曲线加速度
        /// </summary>
        /// <param name="nAxis">轴号</param>
        /// <param name="Sramp">加速度值</param>
        public void SetDirectSramp(int nAxis, float Sramp)
        {
            if (g_handle == (IntPtr)0)
            {
                Console.WriteLine("未链接到控制器!", "提示");
                return;
            }
            zmcaux.ZAux_Direct_SetSramp(g_handle, nAxis, Sramp);
        }
        /// <summary>
        /// 轴连续运动
        /// </summary>
        /// <param name="nAxis">轴号</param>
        /// <param name="dir">运动方向,True为正,False为反</param>
        public void SetDirectSingleVmove(int nAxis, bool dir)
        {
            if (g_handle == (IntPtr)0)
            {
                Console.WriteLine("未链接到控制器!", "提示");
                return;
            }
            if (dir)
            {
                zmcaux.ZAux_Direct_Single_Vmove(g_handle, nAxis, 1);
            }
            else
            {
                zmcaux.ZAux_Direct_Single_Vmove(g_handle, nAxis, -1);
            }
        }

        /// <summary>
        /// 轴寸动
        /// </summary>
        /// <param name="nAxis">轴号</param>
        /// <param name="dir">运动方向,True为正,False为反</param>
        /// <param name="step">寸动距离</param>
        public void SetDirectSingleMove(int nAxis, bool dir, float step)
        {
            if (g_handle == (IntPtr)0)
            {
                Console.WriteLine("未链接到控制器!", "提示");
                return;
            }
            if (dir)
            {
                zmcaux.ZAux_Direct_Single_Move(g_handle, nAxis, step);
            }
            else
            {
                zmcaux.ZAux_Direct_Single_Move(g_handle, nAxis, -1 * step);
            }
        }

        /// <summary>
        /// 轴停止
        /// </summary>
        /// <param name="nAxis">轴号</param>
        public void SetDirectSingleCancel(int nAxis)
        {
            if (g_handle == (IntPtr)0)
            {
                Console.WriteLine("未链接到控制器!", "提示");
                return;
            }
            zmcaux.ZAux_Direct_Single_Cancel(g_handle, nAxis, 2);
        }
    }

    public class ConnectContext
    {
        private Connect cn = null;
        private int ctype = -1;


        public ConnectContext(string type)
        {
            switch (type)
            {
                case "网口":
                    cn = new EthConnect();
                    ctype = 2;
                    break;
                case "串口":
                    cn = new ComConnect();
                    ctype = 1;
                    break;
                case "PCI":
                    cn = new PciConnect();
                    ctype = 4;
                    break;
                case "LOCAL":
                    cn = new LocalConect();
                    ctype = 5;
                    break;
            }
        }

        public string[] ScanConnect()
        {
            return cn.scan();
        }

        public int OpenConnect(ref IntPtr g_handle, string Buffer)
        {
            if (g_handle != (IntPtr)0)
            {
                CloseConnect(g_handle);
            }
            return zmcaux.ZAux_FastOpen(ctype, Buffer, 1000, out g_handle);
        }

        public int CloseConnect(IntPtr g_handle)
        {
            return zmcaux.ZAux_Close(g_handle);
        }
    }

    public abstract class Connect
    {
        public abstract string[] scan();
    }

    class LocalConect : Connect
    {
        public override string[] scan()
        {
            string[] stringArray = new string[] { "LOCAL1" };
            return stringArray;
        }
    }

    class EthConnect : Connect
    {
        public override string[] scan()
        {
            int num;
            string[] sArray;
            StringBuilder buffer = new StringBuilder(10240);
            string buff = "";
            zmcaux.ZAux_SearchEthlist(buffer, 10230, 200);
            buff += buffer;
            sArray = buff.Split(' ');
            num = buff.Split(' ').Length;
            sArray = sArray.Take(num - 1).ToArray();
            return sArray;
        }

    }

    class ComConnect : Connect
    {
        public override string[] scan()
        {
            return SerialPort.GetPortNames();
        }


    }

    class PciConnect : Connect
    {
        public override string[] scan()
        {
            int Card;
            Card = zmcaux.ZAux_GetMaxPciCards();
            string[] tmpstr = new string[Card];

            for (int i = 0; i < Card; i++)
            {
                tmpstr[i] = string.Format("PCI{0:D}", i + 1);
            }
            return tmpstr;
        }
    }
}
