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

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;
                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 devCode = 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("设备编号:" + devCode);
            session.Logger.Info("路由标志:" + routeFlag);
            session.Logger.Info("目标节点地址:" + dstNodeAddr);
            session.Logger.Info("设备类型:" + devType);
            session.Logger.Info("操作类型:" + operType);
            session.Logger.Info("序列seq:" + seq);

            String collectDate = "";
            List<Tag> tags = this.getTags(settings, session);

            Model.BRCJ cj = new Model.BRCJ();
            cj.DEVCODE = devCode;
            cj.LOGTIME = DateTime.Now;

            Model.Alarm alarm = new Model.Alarm();
            
            try
            {
                foreach (Tag tag in tags)
                {
                    if (!(tag is UploadTag))
                    {
                        //非业务处理
                        if (tag != null && tag is SystemDateTag)
                        {
                            SystemDateTag systemDateTag = tag as SystemDateTag;
                            collectDate = systemDateTag.CollectDate;
                            continue;
                        }
                        else if (tag != null && tag is CellTag)
                        {
                            CellTag cellTag = tag as CellTag;
                            cj.CELL = cellTag.Cell;
                            continue;
                        }
                        else if (tag != null && tag is SensorException0Tag)
                        {
                            SensorException0Tag sensorException0 = tag as SensorException0Tag;
                            int state = sensorException0.state;

                            if (state == 1)
                            {
                                alarm.MESSAGE = "采集失败";
                            }
                            else
                            {
                                continue;
                            }

                            alarm.DEVCODE = devCode;
                            alarm.LOGTIME = DateTime.Now;

                            session.Logger.Info("沉降监测仪发送通道一容错信息：oid：" + tag.Oid + ";value:" + state);
                            continue;
                        }
                        else
                        {
                            DefaultTagHandler defaultHandler = new DefaultTagHandler();
                            defaultHandler.resolve(tag, session);
                            continue;
                        }
                    }
                    else
                    {
                        //业务处理
                        UploadTag uploadTag = tag as UploadTag;
                        switch (uploadTag.BizType)
                        {
                            case 18:
                                //沉降值
                                TagHandler cjHandler = new BRCJTagHandler();
                                cjHandler.resolve(tag, session);
                                cj.SEDIMENTATION = (float)cjHandler.DataList[0];
                                cj.UPTIME = Convert.ToDateTime(collectDate + " " + cjHandler.CollecTime);
                                break;
                            case 8:
                                //温度
                                TagHandler tempHandler = new TempTagHandler();
                                tempHandler.resolve(tag, session);
                                cj.TEMPERATURE = (float)tempHandler.DataList[0];
                                break;
                            default:
                                DefaultTagHandler defaultHandler = new DefaultTagHandler();
                                defaultHandler.resolve(tag, session);
                                break;
                        }
                    }
                }

                BLL.BRCJ.getInstance().insert(cj);
                BLL.Alarm.getInstance().insert(alarm);

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