using System;
using System.Collections.Generic;
using System.Text;
using System.Data;
using System.Threading;
using Microsoft.VisualBasic;
using DBFactory;
using ICommLayer;

namespace SocketsTCPIP
{
    /// <summary>
    /// 使用SocketsTCPIP的客户端进行通讯
    /// 发送设备命令类
    /// 创建者：Richard.Liu
    /// </summary>
    public class CSendDeviceOrder: ISendDeviceOrder
    {
        string _commLayerError;

        public string CommLayerError
        {
            get { return _commLayerError; }
            set { _commLayerError = value; }
        }
        
        DBOperator dbo = CClientTCPIP.dbo;
        string AGVAllowSingleFork = CommonClassLib.AppSettings.GetValue("AGVAllowSingleFork");
        public CSendDeviceOrder()
        {
            dbo.Open();
        }
        public bool SendDeviceOrder(int MessageIndex, int TaskIndex, int Order, int DeviceIndex, int StartX, int StartY, int StartZ, int EndX, int EndY, int EndZ,string DoubleFork)
        {
            return true;
        }


        /// <summary>
        /// 每两个字节（一个字）代表一个帧内容
        /// 1客户端连接命令：标志头61；客户端断开命令：标志头62；
        /// 2任务开始命令：标志头63＋任务优先级（1--8）＋取货位编号＋操作码＋送货位编号＋操作码
        /// 操作码含义：0—无动作；1—辅料出库；2—空托盘回收；3—残烟、废纸的回收；4—剩余辅料返库；5—辅料出库，同时空托盘回收
        /// 3取消任务：标志头65＋任务编号（控制台分配的任务编号）
        /// 4申请辊道停止确认（可以向辅料回库口输送机放货）：标志头67
        /// 5查询小车状态：标志头69＋小车编号
        /// </summary>
        /// <param name="MessageIndex">消息编号</param>
        /// <param name="TaskIndex">任务编号</param>
        /// <param name="Order">AGV命令字</param>
        /// <param name="DeviceIndex">设备编号</param>
        /// <param name="StartX">[N1]:取货点</param>
        /// <param name="StartY"></param>
        /// <param name="StartZ"></param>
        /// <param name="EndX">[N2]:放货点</param>
        /// <param name="EndY"></param>
        /// <param name="EndZ"></param>
        /// <returns>发送AGV命令是否成功</returns>
        public bool SendDeviceOrder(int MessageIndex, int TaskIndex, int Order, int DeviceIndex, int StartX, int StartY, int StartZ, int EndX, int EndY, int EndZ)
        {
            //StartX取设备索引 EndX送设备索引

            //28901：前叉左取 28902：前叉左送 28903：前叉右取 28904：前叉右送
            //28905：后叉左取 28906：后叉左送 28907：后叉右取 28908：后叉右送
            //28909：双叉左取 28910：双叉左送 28911：双叉右取 28912：双叉右送

            //20100413根据StartX（取设备索引）获得前（距离车尾远）叉、后（距离车尾近）叉
            //order==1 根据StartX（取设备索引）得到 取左右；order==2 根据EndX（送设备索引）得到 送左右
            //站在车尾沿着行进方向的左、右方向；
            //判断关联双叉是否同步运行
            char useAwayFork = '0';
            char channelLeft = '0';
            int AGVAddress = 0;
            int dorder = 0;
            int _device =  GetAGVNoFromMonitor(TaskIndex);
            byte[] _Sdata;
            
            
            try
            {
                switch (Order)
                {
                    case 1://取货命令 StartX取设备索引
                        GetDeviceInfoFromAGVGate(StartX, ref channelLeft, ref useAwayFork, ref AGVAddress);
                        if ((Model.CGeneralFunction.DoubleForkIfSync(TaskIndex, DeviceIndex, 6) == false) && (AGVAllowSingleFork=="1"))//20100710
                        {//不能同步
                            GetDeviceInfoFromAGVGate(StartX, ref channelLeft, ref useAwayFork, ref AGVAddress);
                            if (useAwayFork == '1')//前叉
                            {
                                if (channelLeft == '1')
                                {
                                    dorder = 28901;//前叉左取
                                }
                                else
                                {
                                    dorder = 28903;//前叉右取
                                }

                            }
                            else//后叉
                            {
                                if (channelLeft == '1')
                                {
                                    dorder = 28905;//后叉左取
                                }
                                else
                                {
                                    dorder = 28907;//后叉右取
                                }
                            }
                        }
                        else
                        {//同步
                            if (channelLeft == '1')
                            {
                                dorder = 28909;//双叉左取
                            }
                            else
                            {
                                dorder = 28911;//双叉右取
                            }

                        }
                        _Sdata = new byte[10];
                        _Sdata[0] = 72;
                        _Sdata[1] = 0;
                        _Sdata[2] = Convert.ToByte(TaskIndex & 255); 
                        _Sdata[3] = Convert.ToByte(TaskIndex >> 8);
                        _Sdata[4] = Convert.ToByte(AGVAddress & 255);
                        _Sdata[5] = Convert.ToByte(AGVAddress >> 8);
                        _Sdata[6] = Convert.ToByte(dorder & 255);
                        _Sdata[7] = Convert.ToByte(dorder >> 8);
                        _Sdata[8] = Convert.ToByte(_device & 255);
                        _Sdata[9] = Convert.ToByte(_device >> 8);

                        return SendData(DeviceIndex, _Sdata);
                        
                    case 2://送货命令
                        GetDeviceInfoFromAGVGate(EndX, ref channelLeft, ref useAwayFork, ref AGVAddress);
                        if ((Model.CGeneralFunction.DoubleForkIfSync(TaskIndex, DeviceIndex, 6) == false) && (AGVAllowSingleFork == "1"))//20100710
                        {//不能同步
                            GetDeviceInfoFromAGVGate(EndX, ref channelLeft, ref useAwayFork, ref AGVAddress);
                            if (useAwayFork == '1')//前叉
                            {
                                if (channelLeft == '1')
                                {
                                    dorder = 28902;//前叉左送
                                }
                                else
                                {
                                    dorder = 28904;//前叉右送
                                }

                            }
                            else//后叉
                            {
                                if (channelLeft == '1')
                                {
                                    dorder = 28906;//后叉左送
                                }
                                else
                                {
                                    dorder = 28908;//后叉右送
                                }
                            }
                        }
                        else
                        {//同步
                            if (channelLeft == '1')
                            {
                                dorder = 28910;//双叉左送
                            }
                            else
                            {
                                dorder = 28912;//双叉右送
                            }

                        }
                        _Sdata = new byte[10];
                        _Sdata[0] = 72;
                        _Sdata[1] = 0;
                        _Sdata[2] = Convert.ToByte(TaskIndex & 255);
                        _Sdata[3] = Convert.ToByte(TaskIndex >> 8);
                        _Sdata[4] = Convert.ToByte(AGVAddress & 255);
                        _Sdata[5] = Convert.ToByte(AGVAddress >> 8);
                        _Sdata[6] = Convert.ToByte(dorder & 255);
                        _Sdata[7] = Convert.ToByte(dorder >> 8);
                        _Sdata[8] = Convert.ToByte(_device & 255);
                        _Sdata[9] = Convert.ToByte(_device >> 8);

                        return SendData(DeviceIndex, _Sdata);
                    case 3:
                        //发送完成的应答帧75

                        _Sdata = new byte[6];
                        _Sdata[0] = 75;
                        _Sdata[1] = 0;
                        TaskIndex = GetAGVTaskFromMonitor(TaskIndex);
                        _Sdata[2] = Convert.ToByte(TaskIndex & 255);
                        _Sdata[3] = Convert.ToByte(TaskIndex >> 8);
                        _Sdata[4] = Convert.ToByte(65535 & 255);
                        _Sdata[5] = Convert.ToByte(65535 >> 8);
                        return SendData(DeviceIndex, _Sdata);
                    case 4:
                        //发送运行
                        GetDeviceInfoFromAGVGate(EndX, ref channelLeft, ref useAwayFork, ref AGVAddress);
                        _Sdata = new byte[10];
                        _Sdata[0] = 72;
                        _Sdata[1] = 0;
                        _Sdata[2] = Convert.ToByte(TaskIndex & 255);
                        _Sdata[3] = Convert.ToByte(TaskIndex >> 8);
                        _Sdata[4] = Convert.ToByte(AGVAddress & 255);
                        _Sdata[5] = Convert.ToByte(AGVAddress >> 8);
                        _Sdata[6] = Convert.ToByte(65535 & 255);//运行
                        _Sdata[7] = Convert.ToByte(65535 >> 8);
                        _Sdata[8] = Convert.ToByte(_device & 255);
                        _Sdata[9] = Convert.ToByte(_device >> 8);
                        return SendData(DeviceIndex, _Sdata);

                    default:
                        break;
                }


                return false;
            }
            catch (Exception ex)
            {
                _commLayerError = this.ToString() + ":SendDeviceOrder---" +ex.Message ;
                return false;
            }

        }
        /// <summary>
        /// 发送AGV命令
        /// </summary>
        /// <param name="MessageIndex">消息编号</param>
        /// <param name="TaskIndex">任务编号</param>
        /// <param name="Order">AGV命令字 ６１：MAN通知LC通讯连接建立；６２MAN通知LC通讯连接断开</param>
        /// <param name="DeviceIndex">设备编号</param>
        /// <returns>发送AGV设备命令是否成功</returns>
        public bool SendDeviceOrder(int MessageIndex, int TaskIndex, int Order, int DeviceIndex, int ArrowDeviceIndex)
        {
            try
            {
                byte[] _Sdata = new byte[2];
                _Sdata[0] =Convert.ToByte(Order); 
                _Sdata[1] = 0;
                _Sdata[2] =Convert.ToByte(TaskIndex & 255);//低八位
                _Sdata[3] = Convert.ToByte(TaskIndex >> 8);//高八位
                
                //根据DeviceIndex,得到Sockets通讯的初始设置
                DataSet ds = dbo.ExceSQL("SELECT  F_DeviceIndex,F_DeviceKindIndex, F_LocalIP,  F_LocalPort, F_RemoteIP,  F_RemotePort  FROM T_Base_Device where F_DeviceIndex=" + DeviceIndex);
                DataView dv = ds.Tables[0].DefaultView;

                if (ds.Tables[0].DefaultView.Count == 0)
                {
                    return false;
                }
                else
                {

                    CClientTCPIP.Send(dv[0]["F_RemoteIP"].ToString(), (int)dv[0]["F_RemotePort"], _Sdata);
                    return true;

                }

            }
            catch (Exception ex)
            {
                _commLayerError = this.ToString() + ":SendDeviceOrder---" + ex.Message;
                return false;
            }

        }
        /// <summary>
        /// 上位机给下位机发送烟箱按品牌码分道信息共15字节,有数据时写入实际数据，否则全部写零
        /// </summary>
        /// <param name="DeviceIndex">码垛位设备号索引</param>
        /// <param name="TobaccoCode">第1--13字节,烟箱码</param>
        /// <param name="HaveFirstProjectCode">第14字节,1-有一号工程码,0-无一号工程码</param>
        /// <param name="IfSmallTobacco">第15字节,1-小烟箱,0-正常烟箱</param>
        /// <returns></returns>
        public bool SendDeviceOrder(int DeviceIndex, string TobaccoCode, bool HaveFirstProjectCode, bool IfSmallTobacco,int Count)
        {
            return true;
        }
        bool SendData(int devID, byte[] _Sdata)
        {
            //根据DeviceIndex,得到Sockets通讯的初始设置
            DataSet ds = dbo.ExceSQL("SELECT  F_DeviceIndex,F_DeviceKindIndex, F_LocalIP,  F_LocalPort, F_RemoteIP,  F_RemotePort  FROM T_Base_Device where F_DeviceIndex=" + devID);
            DataView dv = ds.Tables[0].DefaultView;
            if (dv.Count == 0)
            {
                return false;
            }
            else
            {

                if (CClientTCPIP.Send(dv[0]["F_RemoteIP"].ToString(), Convert.ToInt32(dv[0]["F_RemotePort"]), _Sdata) == false)
                {
                    if (CClientTCPIP.TcpError != null) _commLayerError = CClientTCPIP.TcpError;
                    return false;
                }
                return true;

            }
        }
        /// <summary>
        /// 向PLC的DB区写入数据
        /// </summary>
        /// <param name="ItemNames">标签变量名称数组</param>
        /// <param name="ItemValues">标签值数组</param>
        /// <returns></returns>
        public bool WriteDBData(StringBuilder[] ItemNames, StringBuilder[] ItemValues,int deviceindex)
        {
            return true;
        }
        void GetDeviceInfoFromAGVGate(int agvGateDevice,ref char channelLeft,ref char useAwayFork,ref int AGVAddress)
        {
            DataView dv;
            try
            {
                dv = dbo.ExceSQL("SELECT  F_Address,F_IfChannelLeft,F_UseAwayFork FROM T_Base_AGV_Gate WHERE (F_AGVGateDeviceIndex = " + agvGateDevice + ")").Tables[0].DefaultView;
                if (dv.Count > 0)
                {
                    channelLeft = Convert.ToChar(dv[0]["F_IfChannelLeft"]);
                    useAwayFork = Convert.ToChar(dv[0]["F_UseAwayFork"]);
                    AGVAddress = Convert.ToChar(dv[0]["F_Address"]);
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
            finally
            {
                dv = null;
            }
        }
        int GetAGVNoFromMonitor(int taskIndex)
        {

            DataView dv;
            try
            {
                dv = dbo.ExceSQL("SELECT F_AgvNo FROM T_Monitor_Task WHERE (F_MonitorIndex = " + taskIndex + ") and (F_AgvNo is not null)").Tables[0].DefaultView;
                if (dv.Count > 0)
                {
                    return Convert.ToInt32(dv[0][0]);
                }
                else
                {
                    return 65535;
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
            finally
            {
                dv = null;
            }
        }
        int GetAGVTaskFromMonitor(int taskIndex)
        {

            DataView dv;
            try
            {
                dv = dbo.ExceSQL("SELECT F_AgvTask FROM T_Monitor_Task WHERE (F_MonitorIndex = " + taskIndex + ") and (F_AgvTask is not null)").Tables[0].DefaultView;
                if (dv.Count > 0)
                {
                    return Convert.ToInt32(dv[0][0]);
                }
                else
                {
                    return 65535;
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
            finally
            {
                dv = null;
            }
        }
    }
}
