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

namespace Common
{
    public static class ProtocalData
    {
        /// <summary>
        /// 获取子群数据
        /// </summary>
        /// <param name="subGroupNode"></param>
        /// <returns></returns>
        public static List<List<byte>> GetSubgroupSendData(XmlNode subGroupNode)
        {
            List<List<byte>> sendDatas = new List<List<byte>>();
            int totalFrame = subGroupNode.ChildNodes.Count + 3;//补上配置xml文件版本号、配置数据版本号和全局属性数据

            List<object> textData;
            //=============1、新增配置xml文件版本号=======================
            sendDatas.Add(GetSendData(GetVersionSendData(subGroupNode.Attributes["SettingVersion"].Value), 0xA9, totalFrame, 1));
            //=============2、配置数据版本号===========================
            sendDatas.Add(GetSendData(GetVersionSendData(subGroupNode.Attributes["Version"].Value), 0xA5, totalFrame, 2));
            //=============3、全局属性数据=================================
            sendDatas.Add(GetSendData(GetGlobalSendData(subGroupNode), 0xA3, totalFrame, 3));
            //=============4、设备和动作数据=============================
            for (int i = 0; i < subGroupNode.ChildNodes.Count; i++)
            {
                XmlNode detailNode = subGroupNode.ChildNodes[i];
                textData = new List<object>();
                textData.Add(detailNode.Attributes["Type"].Value);//类型
                int paramCount = Convert.ToInt16(detailNode.Attributes["ParamCount"].Value);
                switch (Convert.ToInt16(detailNode.Attributes["Type"].Value))
                {
                    case 0://设备
                        textData.Add(detailNode.Attributes["DeviceAddress"].Value.Split('.')[0]);//设备地址第一位
                        textData.Add(detailNode.Attributes["DeviceAddress"].Value.Split('.')[1]);//设备地址第二位
                        textData.Add(detailNode.Attributes["DeviceAddress"].Value.Split('.')[2]);//设备地址第三位
                        for (int j = 1; j <= paramCount; j++)
                        {
                            //设备类型、输入回路数，输出回路数为两位字节
                            switch (j)
                            {
                                case 7:
                                case 8:
                                    textData.Add("DeviceAddr");//标记一下，为了转为两位字节
                                    textData.Add(detailNode.Attributes["Param" + j.ToString()].Value);
                                    break;
                                default:
                                    textData.Add(detailNode.Attributes["Param" + j.ToString()].Value);
                                    break;
                            }
                        }
                        break;
                    case 1://动作
                        textData.Add(detailNode.Attributes["DeviceAddress"].Value.Split('.')[0]);//设备地址第一位
                        textData.Add(detailNode.Attributes["DeviceAddress"].Value.Split('.')[1]);//设备地址第二位
                        textData.Add(detailNode.Attributes["DeviceAddress"].Value.Split('.')[2]);//设备地址第三位
                        for (int j = 1; j <= paramCount; j++)
                        {
                            //设备类型、输入地址为两位字节
                            switch (j)
                            {
                                case 4:
                                    textData.Add("DeviceAddr");//标记一下，为了转为两位字节
                                    textData.Add(detailNode.Attributes["Param" + j.ToString()].Value);
                                    break;
                                default:
                                    textData.Add(detailNode.Attributes["Param" + j.ToString()].Value);
                                    break;
                            }
                        }
                        //扩展属性
                        foreach (XmlNode expandNode in detailNode.ChildNodes)
                        {
                            paramCount = Convert.ToInt16(expandNode.Attributes["ParamCount"].Value);
                            for (int j = 1; j <= paramCount; j++)
                            {
                                switch (j)
                                {
                                    case 1:
                                    case 2:
                                    case 4://延时执行内容
                                    case 5://延时执行单位
                                        textData.Add(expandNode.Attributes["Param" + j.ToString()].Value);
                                        break;
                                    default:
                                        //扩展属性都为两位字节
                                        textData.Add("DeviceAddr");//标记一下，为了转为两位字节
                                        textData.Add(expandNode.Attributes["Param" + j.ToString()].Value);
                                        break;
                                }
                            }
                            //扩展属性的输出类型
                            int outTypeParamCount = Convert.ToInt16(expandNode.Attributes["OutTypeParamCount"].Value);
                            switch (outTypeParamCount)
                            {
                                case 1:
                                    textData.Add("DeviceAddr");//标记一下，为了转为两位字节
                                    textData.Add(expandNode.Attributes["Param" + (paramCount + 1).ToString()].Value);
                                    break;
                                case 2:
                                    textData.Add(expandNode.Attributes["Param" + (paramCount + 1).ToString()].Value);
                                    textData.Add(expandNode.Attributes["Param" + (paramCount + 2).ToString()].Value);
                                    break;
                                case 3://背景音乐
                                    textData.Add("DeviceAddr");//标记一下，为了转为两位字节
                                    textData.Add((Convert.ToInt16(expandNode.Attributes["Param" + (paramCount + 1).ToString()].Value) << 0) +
                                        (Convert.ToInt16(expandNode.Attributes["Param" + (paramCount + 2).ToString()].Value) << 12) +
                                        (Convert.ToInt16(expandNode.Attributes["Param" + (paramCount + 3).ToString()].Value) << 8));
                                    break;
                                case 4://地暖
                                    textData.Add("DeviceAddr");//标记一下，为了转为两位字节
                                    textData.Add((Convert.ToInt16(expandNode.Attributes["Param" + (paramCount + 1).ToString()].Value) << 12) +
                                        (Convert.ToInt16(expandNode.Attributes["Param" + (paramCount + 2).ToString()].Value) << 8) +
                                        (Convert.ToInt16(expandNode.Attributes["Param" + (paramCount + 3).ToString()].Value) << 6) +
                                        Convert.ToInt16(expandNode.Attributes["Param" + (paramCount + 4).ToString()].Value));
                                    break;
                                case 5://空调
                                    textData.Add("DeviceAddr");//标记一下，为了转为两位字节
                                    textData.Add((Convert.ToInt16(expandNode.Attributes["Param" + (paramCount + 1).ToString()].Value) << 14) +
                                        (Convert.ToInt16(expandNode.Attributes["Param" + (paramCount + 2).ToString()].Value) << 12) +
                                        (Convert.ToInt16(expandNode.Attributes["Param" + (paramCount + 3).ToString()].Value) << 10) +
                                        (Convert.ToInt16(expandNode.Attributes["Param" + (paramCount + 4).ToString()].Value) << 8) +
                                        Convert.ToInt16(expandNode.Attributes["Param" + (paramCount + 5).ToString()].Value));
                                    break;
                            }
                        }
                        break;
                    case 2://MQTT映射：去掉组地址、设备地址，增加别名（长度20）
                        string deviceType2 = detailNode.Attributes["DeviceType"].Value;
                        textData.Add(deviceType2);
                        textData.Add(detailNode.Attributes["Param1"].Value);
                        if ("0" == deviceType2)
                        {
                            textData.Add(0x00);
                            textData.Add(detailNode.Attributes["Param2"].Value);
                        }
                        else
                        {
                            textData.Add("DeviceAddr");//标记一下，为了转为两位字节
                            textData.Add(detailNode.Attributes["Param2"].Value);
                        }
                        //paramCount = Convert.ToInt16(detailNode.Attributes["ParamCount"].Value);
                        //for (int j = 1; j <= paramCount; j++)
                        //{
                        //    textData.Add(detailNode.Attributes["Param" + j.ToString()].Value);
                        //}
                        byte[] nameBGK = Encoding.GetEncoding("GBK").GetBytes(detailNode.Attributes["Name"].Value);
                        foreach (byte b in nameBGK)
                        {
                            textData.Add(b);
                        }
                        for (int j = nameBGK.Length; j < 20; j++)//不足20位补0
                        {
                            textData.Add(0x00);
                        }
                        break;
                    case 3://BLW映射
                        textData.Add(detailNode.Attributes["GroupAddress"].Value);
                        textData.Add(detailNode.Attributes["DeviceAddress"].Value);
                        string deviceType3 = detailNode.Attributes["DeviceType"].Value;
                        textData.Add(deviceType3);
                        textData.Add(detailNode.Attributes["Param1"].Value);
                        if ("0" == deviceType3)
                        {
                            textData.Add(0x00);
                            textData.Add(detailNode.Attributes["Param2"].Value);
                        }
                        else
                        {
                            textData.Add("DeviceAddr");//标记一下，为了转为两位字节
                            textData.Add(detailNode.Attributes["Param2"].Value);
                        }
                        //textData.Add(detailNode.Attributes["DeviceType"].Value);
                        //paramCount = Convert.ToInt16(detailNode.Attributes["ParamCount"].Value);
                        //for (int j = 1; j <= paramCount; j++)
                        //{
                        //    textData.Add(detailNode.Attributes["Param" + j.ToString()].Value);
                        //}
                        break;
                }
                //每一组设备地址发送数据加入集合
                sendDatas.Add(GetSendData(textData, 0xA2, totalFrame, (i + 4)));//组地址等属性
            }
            return sendDatas;
        }

        /// <summary>
        /// 按所定义的格式获取与RCU主机通讯的数据
        /// </summary>
        /// <param name="textData">数据内容</param>
        /// <param name="mode">模式:时间同步A0，组地址调试A1，子群发布A2，全局属性A3，V80复位开关A4，配置数据版本号A5，485调光A6，网络设置A7</param>
        /// <param name="totalFrame">数据总帧数</param>
        /// <param name="currentFrame">当前帧数</param>
        /// <returns></returns>
        private static List<byte> GetSendData(List<object> textData, byte mode, Int32 totalFrame, Int32 currentFrame)
        {
            //发送数据
            //byte[] demoData = new byte[] { 
            //    0xF0, 0x0F, //数据头
            //    0xA1, //调试模式
            //    0x00, 0x2C, //数据总长度
            //    0x00, 0x01, //数据总帧数
            //    0x00, 0x01, //当前帧数
            //    0x54, 0x33, 0x53, 0x41, //识别码T3SA
            //    0x01, 0x01, 0x02, //组地址属性
            //    0x01, 0x00, 0x23, 0x01, 0x00, 0x00, 0x00, 0x02, //弱电输入
            //    0x01, 0x01, 0x09, 0x01, 0xFF, 0x03, 0x00, 0x00, 0xFF, //弱电输出
            //    0x01, 0x02, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, //强电输出
            //    0x57, 0xDA //CRC16校验
            //};
            List<byte> sendData = new List<byte>();
            sendData.Add(0xF0);//数据头
            sendData.Add(0x0F);//数据头
            sendData.Add(mode);//调试模式
            //数据总长度（除了前面2位数据头，其他都算）
            byte[] dataLen = Tools.Int32ToByte(textData.Count + 13);
            foreach (byte b in dataLen)
            {
                sendData.Add(b);
            }
            //数据总帧数
            dataLen = Tools.Int32ToByte(totalFrame);
            foreach (byte b in dataLen)
            {
                sendData.Add(b);
            }
            //当前帧数
            dataLen = Tools.Int32ToByte(currentFrame);
            foreach (byte b in dataLen)
            {
                sendData.Add(b);
            }
            sendData.Add(0x54);//识别码T3SA
            sendData.Add(0x33);//识别码T3SA
            sendData.Add(0x53);//识别码T3SA
            sendData.Add(0x41);//识别码T3SA
            bool isToByte = false;
            foreach (object obj in textData)
            {
                //遇到“DeviceAddr”标记，则改成2个byte
                if (Convert.ToString(obj) == "DeviceAddr")
                {
                    isToByte = true;
                }
                else
                {
                    if (isToByte)
                    {
                        dataLen = Tools.Int32ToByte2(Convert.ToInt32(obj));//小端
                        foreach (byte b in dataLen)
                        {
                            sendData.Add(b);
                        }
                        isToByte = false;
                    }
                    else
                    {
                        sendData.Add(byte.Parse(obj.ToString()));
                    }
                }
            }
            ushort crc = Tools.CRC16(sendData.ToArray(), sendData.Count);
            sendData.Add(Convert.ToByte(crc & 0xFF));//CRC16校验
            sendData.Add(Convert.ToByte((crc >> 8) & 0xFF));//CRC16校验

            return sendData;
        }
        /// <summary>
        /// 获取配置数据版本号发送数据，version为空时，提供默认值FF,FF,FF
        /// </summary>
        /// <param name="version"></param>
        /// <returns></returns>
        private static List<object> GetVersionSendData(string version)
        {
            List<object> textData = new List<object>();
            if (string.IsNullOrEmpty(version))
            {
                textData.Add(0xFF);
                textData.Add(0xFF);
                textData.Add(0xFF);
            }
            else
            {
                textData.Add(version.Split('.')[0]);
                textData.Add(version.Split('.')[1]);
                textData.Add(version.Split('.')[2]);
            }
            return textData;
        }
        /// <summary>
        /// 获取子群全局属性发送数据
        /// </summary>
        /// <param name="projectGroupAddrID">子群ID</param>
        /// <param name="projectID">项目ID</param>
        /// <returns></returns>
        private static List<object> GetGlobalSendData(XmlNode subGroupNode)
        {
            List<object> textData = new List<object>();
            int paramCount = Convert.ToInt16(subGroupNode.Attributes["ParamCount"].Value);
            for (int j = 1; j <= paramCount; j++)
            {
                textData.Add(subGroupNode.Attributes["Param" + j.ToString()].Value);
            }
            return textData;
        }
    }
}
