using System;
using System.Collections.Generic;
using SuperSocket.SocketBase.Command;
using SuperSocket.SocketBase.Protocol;

namespace BRServer
{
    public class CasicCmd : CommandBase<CasicSession, StringRequestInfo>
    {

        public override string Name
        {
            get
            {
                return "Casic";
            }
        }

        public String getDeviceTypeByPdu(String pduType)
        {
            Int16 btpduType = Int16.Parse(pduType, System.Globalization.NumberStyles.HexNumber);
            int deviceType = btpduType & 0x7F;
            String devType = "";
            switch (deviceType)
            {
                case 0:
                    devType = "未知设备";
                    break;
                case 21:
                    devType = "北燃沉降监测仪";
                    break;
                case 22:
                    devType = "北燃轨道阀回讯装置";
                    break;        
                default:
                    devType = "undefiend";
                    break;
            }
            return devType;
        }

        public String getOpeTypeByPdu(String pduType)
        {
            Int16 btpduType = Int16.Parse(pduType, System.Globalization.NumberStyles.HexNumber);

            int opearType = (btpduType >> 8) & 0xFF;
            String result="";
            switch (opearType) 
            {
                case 1:
                    result =  "GetRequest";
                    break;
                case 2:
                    result = "GetResponse";
                    break;
                case 3:
                    result = "SetRequest";
                    break;
                case 4:
                    result = "TrapRequest";
                    break;
                case 5:
                    result = "TrapResponse";
                    break;
                case 6:
                    result = "OnlineRequest";
                    break;
                case 7:
                    result = "OnlineResponse";
                    break;
                case 8:
                    result = "StartupRequest";
                    break;
                case 9:
                    result = "StartupResponse";
                    break;
                case 10:
                    result = "WakeupRequest";
                    break;
                case 11:
                    result = "WakeupResponse";
                    break;
                case 13:
                    result = "ClientRequest";
                    break;
                case 12:
                    result = "SetResponse";
                    break;
                default:
                    result = "undefined";
                    break;
            }
            return result;
        }

        private List<Tag> getTags(String strTags,CasicSession session)
        {
            List<Tag> tags = new List<Tag>();
            try
            {
                int i = 0;
                while (i < strTags.Length)
                {
                    //get each tag from strTag and construct tag list; 
                    String oid = strTags.Substring(i, 8);

                    int len = Int16.Parse(strTags.Substring(i + 8, 4), System.Globalization.NumberStyles.HexNumber);
                    String value = strTags.Substring(i + 12, len * 2);
                    i = i + 12 + 2 * len;
                    //TODO LIST:Construct a tag according to oid
                    Tag tag = TagFactory.create(oid, len, value);
                    tags.Add(tag);
                }
            }
            catch (Exception e)
            {
                session.Logger.Error("设备上传协议出错:" + e.Message);
            }
            return tags;
        }

        private CellTag getCellTag(List<Tag> tags, CasicSession session)
        {
            foreach (Tag tag in tags)
            {
                if (tag != null && tag is CellTag)
                {
                    return (CellTag)tag;
                }
            }
            return null;
        }

        private SystemDateTag getSystemDateTag(List<Tag> tags)
        {
            foreach (Tag tag in tags)
            {
                if (tag != null && tag is SystemDateTag)
                {
                    return (SystemDateTag)tag;
                }
            }
            return null;
        }

        public override void ExecuteCommand(CasicSession session, StringRequestInfo requestInfo)
        {
            //电信平台需返回200响应码
            session.Send("HTTP/1.1 200 OK\r\n\r\n\r\n");
            session.Close();

            if (requestInfo.Parameters[0] == "CRCERROR")
            {
                session.Logger.Error("CRC校验不通过,上传的数据为：" + requestInfo.Parameters[1]);
                return;
            }

            //TODO: construct the receving casic data
            String preamble = requestInfo.Parameters[0];
            String version = requestInfo.Parameters[1];
            String leng = requestInfo.Parameters[2];
            String deviceId = requestInfo.Parameters[3];
            String routeFlag = requestInfo.Parameters[4];
            String dstNodeAddr = requestInfo.Parameters[5];
            String pduType = requestInfo.Parameters[6];
            String seq = requestInfo.Parameters[7];
            String settings = requestInfo.Parameters[8];
            String deviceId_Telecom = requestInfo.Parameters[9];

            //print the receving data
            String devType = getDeviceTypeByPdu(pduType);
            String operType = getOpeTypeByPdu(pduType);
            session.Logger.Info("AD接收数据:" + requestInfo.Body);
            session.Logger.Info("当前版本:" + version);
            session.Logger.Info("设备编号:" + deviceId);
            session.Logger.Info("路由标志:" + routeFlag);
            session.Logger.Info("目标节点地址:" + dstNodeAddr);
            session.Logger.Info("设备类型:" + devType);
            session.Logger.Info("操作类型:" + operType);
            session.Logger.Info("序列seq:" + seq);

            List<Tag> tags = this.getTags(settings, session);
            CellTag cellTag = this.getCellTag(tags, session);
            SystemDateTag systemDateTag = this.getSystemDateTag(tags);

            try
            {
                //TODO LIST:处理主动上报的数据、参数查、询参数设置
                TagHandler systemDateHandler = new SystemDateTagHandler();
                TagHandler cellTagHandler = new CellTagHandler();
                TagHandler BRTagHandler = new BRTagHandler();

                systemDateHandler.NextHandler = cellTagHandler;
                cellTagHandler.NextHandler = BRTagHandler;

                foreach (Tag tag in tags)
                {
                    //采用责任链的方式来处理各个tag
                    systemDateHandler.handleTag(tag, deviceId, cellTag,
                        systemDateTag, session);
                }

                //回复校时信息
                CasicSender sender = new CasicSender(null);
                sender.doSendTimeConfig(deviceId, version, devType, session, "3", deviceId_Telecom);
            }
            catch (Exception e)
            {
                session.Logger.Error(e.ToString());
            }
        }
    }
}
