using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using System.Text;

namespace Node
{
    //节点命令
    public enum CMD_ROUTE : byte
    {
        CMD_ROUTE_V0 = 0,
        CMD_ROUTE_NONE = 10,
        CMD_ROUTE_FLOOD = 11,
        CMD_ROUTE_ADD = 12,
        CMD_ROUTE_SUB = 13,
    }
        
    //节点命令
    public enum CMD_ID_NODE : int
    {
        CMD_ID_NODE_DATA = 0,       //0x00. 数据帧
        CMD_ID_NODE_ADDRREQ,		//0x01. 地址查询
        CMD_ID_NODE_ADDRSET,		//0x02. 地址设置
        CMD_ID_NODE_CHREQ,		    //0x03. 通道查询
        CMD_ID_NODE_CHSET, 		    //0x04. 通道设置
        CMD_ID_NODE_ROUTREQ, 		//0x05. 路由查询
        CMD_ID_NODE_ROUTSET,		//0x06. 路由设置
        CMD_ID_NODE_TRANUMREQ,		//0x07. 最大转发跳数查询
        CMD_ID_NODE_TRANUMSET,		//0x08. 最大转发跳数设置
        CMD_ID_NODE_BRTSET,		    //0x09. 波特率设置
        CMD_ID_NODE_CSMAREQ,		//0x0A. CSMA/CA策略查询
        CMD_ID_NODE_CSMASET,		//0x0B. CSMA/CA策略设置
        CMD_ID_NODE_MACREQ,		    //0x0C. 通过ZIG_IP地址查询ZIG_MAC地址
        CMD_ID_NODE_MACIPREQ,		//0x0D. 通过ZIG_MAC地址查询ZIG_MACIP地址
        CMD_ID_NODE_MACIPSET,		//0x0E. 通过ZIG_MAC地址设置ZIG_IP地址
        CMD_ID_NODE_MACSET,		    //0x0F. 设置ZIG_MAC地址
        CMD_ID_NODE_MACFLAGREQ,	    //0x10. 广播查询ZIG_MAC地址应答标志查询
        CMD_ID_NODE_MACFLAGSET,     //0x11. 广播查询ZIG_MAC地址应答标志设置
        CMD_ID_NODE_MACBROADREQ,    //0x12. 广播查询ZIG_MAC地址
        CMD_ID_NODE_CMDMAX,

        CMD_ID_NODE_ACK = 0xA0,     //0xA0. 应答帧
        CMD_ID_NODE_ADDRACK,		//0xA1. 地址应答
        CMD_ID_NODE_CHACK, 		    //0xA2. 通道应答
        CMD_ID_NODE_ROUTACK,		//0xA3. 路由应答
        CMD_ID_NODE_TRANUMACK,		//0xA4. 最大转发跳数应答
        CMD_ID_NODE_CSMAACK,		//0xA5. CSMA/CA策略应答
        CMD_ID_NODE_MACIPACK,		//0xA6. MACIP地址应答
        CMD_ID_NODE_MACFLAGACK,	    //0xA7. 广播查询ZIG_MAC地址应答标志应答

        NODE_CMD_UNKNOWN = 0xFFFF,
    }

    //节点应答
    public enum CMD_ACK_NODE : int
    {
        CMD_ACK_NODEK_NONE = 0,      //0x00. 正确返回
        CMD_ACK_NODE_CHK,            //0x01. 校验和错误
        CMD_ACK_NODE_LEN,			 //0x02. 长度错误
        CMD_ACK_NODE_CMD,			 //0x03, 命令字错误
        CMD_ACK_NODE_ADDREQ,	     //0x04, 查询地址失败
        CMD_ACK_NODE_ADDSET,		 //0x05, 设置地址失败
        CMD_ACK_NODE_CHREQ,		     //0x06, 查询通道失败
        CMD_ACK_NODE_CHSET,		     //0x07, 设置通道失败
        CMD_ACK_NODE_ROUTREQ, 		 //0x08, 查询路由功能失败
        CMD_ACK_NODE_ROUTSET, 		 //0x09, 设置路由功能失败
        CMD_ACK_NODE_BRTSET,		 //0x0A, 设置波特率失败
        CMD_ACK_NODE_CSMAREQ,		 //0x0B, 查询CSMA/CA功能失败
        CMD_ACK_NODE_CSMASET,		 //0x0C, 设置CSMA/CA功能失败
        CMD_ACK_NODE_MACREQ,		 //0x0D, 通过ZIG_IP地址查询ZIG_MAC地址失败
        CMD_ACK_NODE_MACIPREQ,		 //0x0E, 通过ZIG_MAC地址查询ZIG_IP地址失败
        CMD_ACK_NODE_MACIPSET,		 //0x0F, 通过ZIG_MAC地址设置ZIG_IP地址失败
        CMD_ACK_NODE_MACSET,		 //0x10, ZIG_MAC地址设置失败
        CMD_ACK_NODE_MACFLAGREQ,	 //0x11, 广播查询ZIG_MAC地址应答开关查询失败
        CMD_ACK_NODE_MACFLAGSET,	 //0x12, 广播查询ZIG_MAC地址应答开关设置失败

        CMD_ACK_NODE_MAX 
    }


    //正确应答帧的委托函数
    public delegate int CorrectACKHandle(byte[] datagram, int len);

    public class CNodeBase
    {
        protected UInt64 mac;
        protected int networkID;
        protected int internalID;
        protected int groupID;
        protected int chID;
        protected int broute;
        protected int bcsma;
        protected int macflag;
        protected int lastSetCmd;
        private CorrectACKHandle AckHandle = null;

        //public CNodeBase();
        public CNodeBase(int netID, int innerID)
        {
            networkID = netID;
            internalID = innerID;
            groupID = 0;
        }

        public void SetDelegate(CorrectACKHandle handle)
        {
            AckHandle = handle;
        }
        //public virtual ~ClassNode();

        public void SetMac(UInt64 macaddr)
        {
            mac = macaddr;
        }

        public UInt64 GetMac()
        {
            return mac;
        }

        public void SetchID(int chid)
        {
            chID = chid;
        }

        public int GetchID()
        {
            return chID;
        }
        public void Setbcsma(int bCSMA)
        {
            bcsma = bCSMA;
        }

        public int Getbcsma()
        {
            return bcsma;
        }
        public void Setbroute(int broute)
        {
            this.broute = broute;
        }

        public int Getbroute()
        {
            return broute;
        }
        public void Setbmacflag(int Macflag)
        {
            macflag = Macflag;
        }

        public int Getmacflag()
        {
            return macflag;
        }
        public void SetNetID(int networkID)
        {
            this.networkID = networkID;
        }
        public int GetNetID()
        {
            return networkID;
        }
        public void SetNodeID(int internalID)
        {
            this.internalID = internalID;
        }
        public int GetNodeID()
        {
            return internalID;
        }
        public int GetGroupID()
        {
            return groupID;
        }

        public void SetGroupID(int gID)
        {
            groupID = gID;
        }

        public int GetLastSetCmd()
        {
            return lastSetCmd;
        }

        //通过IP查询IP，主要用于根节点查询
        public byte[] CombineCmd_GetIP(uint cmdSN, CMD_ROUTE route)
        {
            byte[] cmd = new byte[13];
            CombineCmd_Pre(ref cmd, 13, cmdSN, networkID, route, 0, internalID, CMD_ID_NODE.CMD_ID_NODE_ADDRREQ);
            //cmd content
            //chk
            cmd[12] = CalculateCheckSum(cmd, 12);
            return cmd;
        }
        //通过IP查询IP，主要用于根节点查询
        public byte[] CombineCmd_GetIP(uint cmdSN, CMD_ROUTE route, int _networkID, int _internalID,int _group)
        {
            byte[] cmd = new byte[13];

            CombineCmd_Pre(ref cmd, 13, cmdSN, _networkID, route, (byte)_group, _internalID, CMD_ID_NODE.CMD_ID_NODE_ADDRREQ);

            //cmd content

            //chk
            cmd[12] = CalculateCheckSum(cmd, 12);

            return cmd;
        }
        //通过IP设置IP，主要用于根节点设置
        public byte[] CombineCmd_IPSetIP(uint cmdSN, CMD_ROUTE route, int _networkID, int _internalID, int _group)
        {
            byte[] cmd = new byte[19];

            CombineCmd_Pre(ref cmd, 19, cmdSN, this.networkID, route, (byte)0, this.internalID, CMD_ID_NODE.CMD_ID_NODE_ADDRSET);

            //cmd content
            cmd[12] = (byte)(_networkID >> 8);
            cmd[13] = (byte)_networkID;
            cmd[14] = 0;
            cmd[15] = (byte)_group;
            cmd[16] = (byte)(_internalID >> 8);
            cmd[17] = (byte)_internalID;

            //chk
            cmd[18] = CalculateCheckSum(cmd, 18);

            return cmd;
        }
        //通过MAC设置IP
        public byte[] CombineCmd_SetIP(uint cmdSN, CMD_ROUTE route, UInt64 macaddr, int netid, int nodeid, int groupid)
        {
            byte[] cmd = new byte[27];

            CombineCmd_Pre(ref cmd, 27, cmdSN, 0, route, 0, 0, CMD_ID_NODE.CMD_ID_NODE_MACIPSET);

            //cmd content
            cmd[12] = (byte)(macaddr >> 56);
            cmd[13] = (byte)(macaddr >> 48);
            cmd[14] = (byte)(macaddr >> 40);
            cmd[15] = (byte)(macaddr >> 32);
            cmd[16] = (byte)(macaddr >> 24);
            cmd[17] = (byte)(macaddr >> 16);
            cmd[18] = (byte)(macaddr >> 8);
            cmd[19] = (byte)macaddr;
            cmd[20] = (byte)(netid >> 8);
            cmd[21] = (byte)netid;
            cmd[22] = 0;
            cmd[23] = (byte)groupid;
            cmd[24] = (byte)(nodeid >> 8);
            cmd[25] = (byte)nodeid;

            //chk
            cmd[26] = CalculateCheckSum(cmd, 26);

            return cmd;
        }
        //通过MAC查询IP
        public byte[] CombineCmd_QurIP(uint cmdSN, CMD_ROUTE route,UInt64 macaddr)
        {
            byte[] cmd = new byte[21];

            CombineCmd_Pre(ref cmd, 21, cmdSN, 0, route, 0, 0, CMD_ID_NODE.CMD_ID_NODE_MACIPREQ);

            //cmd content
            cmd[12] = (byte)(macaddr >> 56);
            cmd[13] = (byte)(macaddr >> 48);
            cmd[14] = (byte)(macaddr >> 40);
            cmd[15] = (byte)(macaddr >> 32);
            cmd[16] = (byte)(macaddr >> 24);
            cmd[17] = (byte)(macaddr >> 16);
            cmd[18] = (byte)(macaddr >> 8);
            cmd[19] = (byte)macaddr;            

            //chk
            cmd[20] = CalculateCheckSum(cmd, 20);

            return cmd;
        }
		
        //通过IP查询MAC
        public byte[] CombineCmd_QurMAC(uint cmdSN, CMD_ROUTE route)
        {
            byte[] cmd = new byte[13];

            CombineCmd_Pre(ref cmd, 13, cmdSN, networkID, route, (byte)groupID, internalID, CMD_ID_NODE.CMD_ID_NODE_MACREQ);
            //chk
            cmd[12] = CalculateCheckSum(cmd, 12);

            return cmd;
        }
		
        //设置MAC地址
        public byte[] CombineCmd_SetMAC(uint cmdSN, CMD_ROUTE route, UInt64 macaddr)
        {
            byte[] cmd = new byte[21];

            CombineCmd_Pre(ref cmd, 21, cmdSN, networkID, route, (byte)groupID, internalID, CMD_ID_NODE.CMD_ID_NODE_MACSET);

            //cmd content
            cmd[12] = (byte)(macaddr >> 56);
            cmd[13] = (byte)(macaddr >> 48);
            cmd[14] = (byte)(macaddr >> 40);
            cmd[15] = (byte)(macaddr >> 32);
            cmd[16] = (byte)(macaddr >> 24);
            cmd[17] = (byte)(macaddr >> 16);
            cmd[18] = (byte)(macaddr >> 8);
            cmd[19] = (byte)macaddr;

            //chk
            cmd[20] = CalculateCheckSum(cmd, 20);

            return cmd;
        }
        //查询RF通道号
        public byte[] CombineCmd_QurRFChannel(uint cmdSN, CMD_ROUTE route)
        {
            byte[] cmd = new byte[13];

            CombineCmd_Pre(ref cmd, 13, cmdSN, networkID, route, (byte)groupID, internalID, CMD_ID_NODE.CMD_ID_NODE_CHREQ);          
            //chk
            cmd[12] = CalculateCheckSum(cmd, 12);

            return cmd;
        }
        //设置RF通道号
        public byte[] CombineCmd_SetRFChannel(uint cmdSN, CMD_ROUTE route,byte chid)
        {
            byte[] cmd = new byte[14];

            CombineCmd_Pre(ref cmd, 14, cmdSN, networkID, route, (byte)groupID, internalID, CMD_ID_NODE.CMD_ID_NODE_CHSET);
            cmd[12] = chid;
            //chk
            cmd[13] = CalculateCheckSum(cmd, 13);

            return cmd;
        }
        //查询CSMA功能
        public byte[] CombineCmd_QurCSMA(uint cmdSN, CMD_ROUTE route)
        {
            byte[] cmd = new byte[13];

            CombineCmd_Pre(ref cmd, 13, cmdSN, networkID, route, (byte)groupID, internalID, CMD_ID_NODE.CMD_ID_NODE_CSMAREQ);
            //chk
            cmd[12] = CalculateCheckSum(cmd, 12);

            return cmd;
        }
        //设置CSMA功能
        public byte[] CombineCmd_SetCSMA(uint cmdSN, CMD_ROUTE route,byte CSMA)
        {
            byte[] cmd = new byte[14];

            CombineCmd_Pre(ref cmd, 14, cmdSN, networkID, route, (byte)groupID, internalID, CMD_ID_NODE.CMD_ID_NODE_CSMASET);
            cmd[12] = CSMA;
            //chk
            cmd[13] = CalculateCheckSum(cmd, 13);

            return cmd;
        }
        //查询广播查询MAC地址应答开关
        public byte[] CombineCmd_MACFlagReq(uint cmdSN, CMD_ROUTE route)
        {
            byte[] cmd = new byte[21];

            CombineCmd_Pre(ref cmd, 21, cmdSN, 0, route, 0, 0, CMD_ID_NODE.CMD_ID_NODE_MACFLAGREQ);
          
            //cmd content
            cmd[12] = (byte)(mac >> 56);
            cmd[13] = (byte)(mac >> 48);
            cmd[14] = (byte)(mac >> 40);
            cmd[15] = (byte)(mac >> 32);
            cmd[16] = (byte)(mac >> 24);
            cmd[17] = (byte)(mac >> 16);
            cmd[18] = (byte)(mac >> 8);
            cmd[19] = (byte)mac; 
   
            //chk
            cmd[20] = CalculateCheckSum(cmd, 20);
            return cmd;
        }
        //设置广播查询MAC地址应答开关
        public byte[] CombineCmd_MACFlagSet(uint cmdSN, CMD_ROUTE route, byte MACFlag)
        {
            byte[] cmd = new byte[22];

            CombineCmd_Pre(ref cmd, 22, cmdSN, 0, route, 0, 0, CMD_ID_NODE.CMD_ID_NODE_MACFLAGSET);
            //cmd content
            cmd[12] = (byte)(mac >> 56);
            cmd[13] = (byte)(mac >> 48);
            cmd[14] = (byte)(mac >> 40);
            cmd[15] = (byte)(mac >> 32);
            cmd[16] = (byte)(mac >> 24);
            cmd[17] = (byte)(mac >> 16);
            cmd[18] = (byte)(mac >> 8);
            cmd[19] = (byte)mac; 
            cmd[20] = MACFlag;
            //chk
            cmd[21] = CalculateCheckSum(cmd, 21);

            return cmd;
        }
        //查询路由转发能力
        public byte[] CombineCmd_QurRoute(uint cmdSN, CMD_ROUTE route)
        {
            byte[] cmd = new byte[13];

            CombineCmd_Pre(ref cmd, 13, cmdSN, networkID, route, (byte)groupID, internalID, CMD_ID_NODE.CMD_ID_NODE_ROUTREQ);
            //chk
            cmd[12] = CalculateCheckSum(cmd, 12);

            return cmd;
        }
        //设置路由转发能力
        public byte[] CombineCmd_SetRoute(uint cmdSN, CMD_ROUTE route, byte Route)
        {
            byte[] cmd = new byte[14];

            CombineCmd_Pre(ref cmd, 14, cmdSN, networkID, route, (byte)groupID, internalID, CMD_ID_NODE.CMD_ID_NODE_ROUTSET);
            cmd[12] = Route;
            //chk
            cmd[13] = CalculateCheckSum(cmd, 13);

            return cmd;
        }     
        public int HandleData(byte[] datagram, int len)
        {
            int ret = (int)CMD_ACK_NODE.CMD_ACK_NODE_LEN;
            
            //检验帧是否正确
            if (CalculateCheckSum(datagram, len - 1) != datagram[len - 1])
            {
                ret = (int)CMD_ACK_NODE.CMD_ACK_NODE_CHK;
            }
            else
            {
                CMD_ID_NODE ackCmd = (CMD_ID_NODE)datagram[11];

                //节点通用处理
                switch (ackCmd)
                {
                    //数据帧
                    case CMD_ID_NODE.CMD_ID_NODE_DATA:
                        {
                            if (AckHandle != null)
                            {
                                ret = AckHandle(datagram, len);
                            }
                            break;
                        }

                    //ACK
                    case CMD_ID_NODE.CMD_ID_NODE_ACK:
                        {
                            if (len == 14)
                            {
                                ret = datagram[12];                                
                            }
                            break;
                        }

                    //地址应答
                    case CMD_ID_NODE.CMD_ID_NODE_ADDRACK:
                        {
                            if (len == 19)
                            {
                                networkID = (int)((datagram[12] << 8) + datagram[13]);
                                groupID = datagram[15];
                                internalID = (int)((datagram[16] << 8) + datagram[17]);
                                ret = 0;
                            }
                            break;
                        }

                    //通道应答
                    case CMD_ID_NODE.CMD_ID_NODE_CHACK:
                        {
                            if (len == 14)
                            {
                                chID = datagram[12];
                                ret = 0;
                            }
                            break;
                        }

                    //路由应答
                    case CMD_ID_NODE.CMD_ID_NODE_ROUTACK:
                        {
                            if (len == 14)
                            {
                                broute = datagram[12];
                                ret = 0;
                            }
                            break;
                        }

                    //CSMA/CA策略应答
                    case CMD_ID_NODE.CMD_ID_NODE_CSMAACK:
                        {
                            if (len == 14)
                            {
                                bcsma = datagram[12];
                                ret = 0;
                            }
                            break;
                        }

                    //广播查询MAC地址应答
                    case CMD_ID_NODE.CMD_ID_NODE_MACFLAGACK:
                        {
                            if (len == 22)
                            {
                                macflag = datagram[20];
                                ret = 0;
                            }
                            break;
                        }
                    //MACIP地址应答
                    case CMD_ID_NODE.CMD_ID_NODE_MACIPACK:
                        {
                            if (len == 27)
                            {
                                UInt64 tmp64 = datagram[12];
                                mac = (tmp64 << 56);
                                tmp64 = datagram[13];
                                mac += (tmp64 << 48);
                                tmp64 = datagram[14];
                                mac += (tmp64 << 40);
                                tmp64 = datagram[15];
                                mac += (tmp64 << 32);
                                tmp64 = datagram[16];
                                mac += (tmp64 << 24);
                                tmp64 = datagram[17];
                                mac += (tmp64 << 16);
                                tmp64 = datagram[18];
                                mac += (tmp64 << 8);
                                mac += datagram[19];
                                //mac = (UInt64)((datagram[12] << 56) + (datagram[13] << 48) + (datagram[14] << 40) + (datagram[15] << 32) + (datagram[16] << 24) + (datagram[17] << 16) + (datagram[18] << 8) + datagram[19]);
                                networkID = (int)((datagram[20] << 8) + datagram[21]);
                                groupID = datagram[22];
                                internalID = (int)((datagram[24] << 8) + datagram[25]);
                                ret = 0;
                            }
                            break;
                        }

                    default:
                        {
                            ret = (int)CMD_ACK_NODE.CMD_ACK_NODE_CMD;
                            break;
                        }
                }                
            }
            
            return ret;
        }

        /// <summary>
        /// 校验和计算函数
        /// </summary>
        /// <param name="SendCMDFrame">发送帧</param>
        public byte CalculateCheckSum(byte[] datagram, int len)
        {
            //初始化变量
            byte temp_Sum = 0x00;
            for (int i = 0; i < len; i++)
            {
                temp_Sum += datagram[i];
            }
            return temp_Sum;
        }

        //组帧
        public void CombineCmd_Pre(ref byte[] cmd, byte cmdlen, uint cmdSN, int netid, CMD_ROUTE route, byte group, int nodeid, CMD_ID_NODE cmdid)
        {
            //长度
            cmd[0] = cmdlen;

            //sn
            cmd[1] = (byte)(cmdSN >> 24);
            cmd[2] = (byte)(cmdSN >> 16);
            cmd[3] = (byte)(cmdSN >> 8);
            cmd[4] = (byte)cmdSN;

            //netid
            cmd[5] = (byte)(netid >> 8);
            cmd[6] = (byte)netid;

            //route
            cmd[7] = (byte)route;

            //group
            cmd[8] = group;

            //nodeid;
            cmd[9] = (byte)(nodeid >> 8);
            cmd[10] = (byte)nodeid;

            //cmdid
            cmd[11] = (byte)cmdid;
        }
    }
}
