using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Platform.Common;
using Platform.Common.RunningParameters;
using Platform.Common.LogSystem;

namespace TellerSystem.Communication.Package
{
    /// <summary>
    /// 8583 128域类型报文，Tcp通讯方式的组包，解包处理。承德渠道
    /// </summary>
    class Msg858301 : IPackage
    {
        //定义静态实例
        public static Msg858301 Instance;
        /// <summary>
        ///静态实例初始化函数
        /// </summary>
        static public Msg858301 GetInstance()
        {
            if (Instance == null)
            {
                Instance = new Msg858301();
            }
            return Instance;
        }

        /// <summary>
        /// 组包操作
        /// </summary>
        /// <returns>报文数据包</returns>
        public byte[] Integrate(Message msg)
        {
            byte[] returnData = null;

            try
            {
                returnData = DoIntegrate(msg);
            }
            catch (Exception ex)
            {
                //写错误信息
                PlatformLogger.SystemErrorInfo("组包发生异常：", ex);
                throw;
            }
            return returnData;
        }

        /// <summary>
        /// 解包操作
        /// </summary>
        /// <param name="msg">核心返回数据包</param>
        /// <param name="data">核心返回数据包</param>
        /// <returns></returns>
        public bool Analyze(Message msg, byte[] data)
        {
            try
            {
                //进行解包处理
                DoAnalyze(msg, data);
            }
            catch (Exception ex)
            {

                return false;
            }
            return true;
        }

        #region 组包处理

        /// <summary>
        /// 组包处理
        /// </summary>
        /// <param name="msg"></param>
        /// <returns></returns>
        private byte[] DoIntegrate(Message msg)
        {
            #region new
            ///*******************************************
            // * 组包规则：
            // * msgHeader         byte[68]   Tuxedo报文头
            // * msgData           byte[]     报文数据
            // * fileFlag          byte       是否发送附件 
            // * *****************************************/

            ////文件标志
            //byte fileFlag = (byte)(msg.FileFlag ? 0x7f : 0xff);
            ////报文数据
            //byte[] bitMapData;
            //var fdData = msg.IntegrateFd(out bitMapData);
            //byte[] msgKindData = PlatformSettings.Encoding.GetBytes(MsgParames.MsgType.PadLeft(5, '0'));
            //var msgData = new byte[msgKindData.Length + bitMapData.Length + fdData.Length];
            //msgKindData.CopyTo(msgData, 0);
            //bitMapData.CopyTo(msgData, msgKindData.Length);
            //fdData.CopyTo(msgData, msgKindData.Length + bitMapData.Length);
            ////加密报文数据
            //MsgPackage.Encrypt(msgData, Encoding.ASCII.GetBytes(MsgParames.KeyStr), 1);
            ////报文头
            //var msgHeader = GetMsgT(msg, msgData.Length.ToString()).ToArray<byte>();
            ////组装报文
            //var totalData = new byte[msgHeader.Length + msgData.Length + 1];
            //msgHeader.CopyTo(totalData, 0);
            //msgData.CopyTo(totalData, msgHeader.Length);
            //totalData[totalData.Length - 1] = fileFlag;

            //return totalData;
            #endregion


            #region deleted
            //报文数据区
            byte[] msgData;
            //报文总长度
            int totalLen;
            //8位长度对应字符串
            string strLen;
            //报文数据区的长度
            int msgDataLen;
            //60位报文头
            string msgTitle;
            //5报文类型
            byte[] msgKindByte;
            //位图区域
            byte[] bitMapByte = new byte[16];
            //有效数据内容
            string bitDataStr = string.Empty;
            byte[] bitDataByte;
            //组包数据包
            byte[] totalMsgData;

            //文件标志 0xff==no file   0x7f==file
            byte fileFlag;
            //根据当前交易附件标志设置文件标志
            if (msg.FileFlag)
            {
                fileFlag = 0x7f;
            }
            //无文件
            else
            {
                fileFlag = 0xff;
            }
            try
            {
                //报文类型
                msgKindByte = PlatformSettings.Encoding.GetBytes("00000");
                //组织报文数据区域信息，位图区，数据区
                //GetBitData(msg, bitMapByte, ref bitDataStr);
                //bitDataByte = PlatformSettings.Encoding.GetBytes(bitDataStr);
                bitDataByte = msg.IntegrateFd(out bitMapByte);

                //报文数据区长度
                msgDataLen = msgKindByte.Length + bitMapByte.Length + bitDataByte.Length;
                //报文总长度
                totalLen = msgDataLen + 68;
                //8位长度对应字符串
                strLen = Convert.ToString(totalLen).PadLeft(8, '0');
                //60位报文头
                msgTitle = msgDataLen.ToString().PadLeft(4, '0').PadLeft(68, ' ');//GetMsgT(msg, msgDataLen.ToString());

                //合并5位报文类型，位图，数据区域
                msgData = new byte[msgDataLen];
                //合并操作
                for (int i = 0; i < msgData.Length; i++)
                {
                    if (i < msgKindByte.Length)
                    {
                        msgData[i] = msgKindByte[i];
                    }

                    if (i > msgKindByte.Length - 1 & i < msgKindByte.Length + bitMapByte.Length)
                    {
                        msgData[i] = bitMapByte[i - msgKindByte.Length];
                    }
                    if (i > msgKindByte.Length + bitMapByte.Length - 1)
                    {
                        msgData[i] = bitDataByte[i - msgKindByte.Length - bitMapByte.Length];
                    }
                }

                //MsgPackage.LogObj.Debug("加密前数据："+PlatformSettings.Encoding.GetString(msgData));
                //加密报文数据区
                //MsgPackage.Encrypt(msgData, Encoding.ASCII.GetBytes(CommonSettings.KeyStr), 1);
                //MsgPackage.LogObj.Debug("加密后数据：" + PlatformSettings.Encoding.GetString(msgData));

                //合并组包数据
                //8位的报文长度
                byte[] len8 = PlatformSettings.Encoding.GetBytes(strLen);//new byte[0];
                //报文头字节数组
                byte[] msgTitleByte = PlatformSettings.Encoding.GetBytes(msgTitle);
                totalMsgData = new byte[len8.Length + msgTitleByte.Length + msgData.Length + 1];
                for (int j = 0; j < totalMsgData.Length - 1; j++)
                {
                    if (j < len8.Length)
                    {
                        totalMsgData[j] = len8[j];
                    }
                    if (j > len8.Length - 1 & j < len8.Length + msgTitleByte.Length)
                    {
                        totalMsgData[j] = msgTitleByte[j - len8.Length];
                    }
                    if (j > len8.Length + msgTitleByte.Length - 1)
                    {
                        totalMsgData[j] = msgData[j - len8.Length - msgTitleByte.Length];
                    }
                }
                //设置文件标志位
                totalMsgData[totalMsgData.Length - 1] = fileFlag;

                //处理附件
                if (msg.FileFlag)
                {
                    //文件追加到数据后
                    var file = PlatformSettings.Encoding.GetBytes(Message.Cconv(msg.FileData));//生僻字转义：文件组包处理
                    var lenData = PlatformSettings.Encoding.GetBytes(file.Length.ToString().PadLeft(8, '0'));
                    var fileName = !string.IsNullOrEmpty(msg._filename) ? PlatformSettings.Encoding.GetBytes(msg._filename.PadRight(30)) : PlatformSettings.Encoding.GetBytes((LoginUserInfo.KinbrNo + LoginUserInfo.TtyName).PadRight(30));
                    var ret = new byte[totalMsgData.Length + fileName.Length + lenData.Length + file.Length + 1];
                    Array.Copy(totalMsgData, ret, totalMsgData.Length);
                    Array.Copy(fileName, 0, ret, totalMsgData.Length, fileName.Length);
                    Array.Copy(lenData, 0, ret, totalMsgData.Length + fileName.Length, lenData.Length);
                    Array.Copy(file, 0, ret, totalMsgData.Length + fileName.Length + lenData.Length, file.Length);
                    //补充一个结束字符
                    ret[ret.Length - 1] = 0xff;
                    totalMsgData = ret;
                }
                //MsgPackage.LogObj.Debug("报文整体数据：" + PlatformSettings.Encoding.GetString(totalMsgData));
            }
            catch (Exception ex)
            {
                //写错误信息
                PlatformLogger.SystemErrorInfo("组包发生异常！", ex);
                throw;
            }
            return totalMsgData;
            #endregion
        }

        /// <summary>
        /// 生成TUXEDO方式报文头
        /// </summary>
        /// <param name="msg">域信息</param>
        /// <param name="msgDataLen"></param>
        /// <returns></returns>
        private string GetMsgT(Message msg, string msgDataLen)
        {
            string clnm = "";                 //5位   空串
            string svcnm = "";                //15位  Tuxedo交易服务名
            string reqtype = "";              //1位   "4"
            string branchNo = "";             //10位   机构编号
            string tty = "";                  //12位   终端号
            string titaOr8583;                //1位   代码中的值 8’
            string cbs = "";                  //10位  空串
            string macflg = "";               //1位   空串
            string mac = "";                  //8位   空串
            string result = "";               //1位   '0'
            string len = "";                  //4位   8583数据区长度
            //TUXEDO方式报文头
            StringBuilder tmpMstTile = new StringBuilder();

            //设置对应变量的值
            clnm = "".PadLeft(5, ' ');
            tmpMstTile.Append(clnm);
            svcnm = "".PadLeft(15, ' ');
            tmpMstTile.Append(svcnm);
            reqtype = "4";
            tmpMstTile.Append(reqtype);
            //TODO:机构号扩展为10位，故报文大小变成68
            branchNo = msg.Fd3.PadLeft(10, ' ');
            tmpMstTile.Append(branchNo);
            //TODO:由于tty采用12位，故修改为12位（保证核心已经修改）
            //tty = msg.Fd10.PadLeft(9, ' ');
            tty = msg.Fd10.PadLeft(12, ' ');
            tmpMstTile.Append(tty);
            titaOr8583 = "8";
            tmpMstTile.Append(titaOr8583);
            cbs = "".PadLeft(10, ' ');
            tmpMstTile.Append(cbs);
            macflg = "".PadLeft(1, ' ');
            tmpMstTile.Append(macflg);
            mac = "".PadLeft(8, ' ');
            tmpMstTile.Append(mac);
            result = "0";
            tmpMstTile.Append(result);
            len = msgDataLen.PadLeft(4, '0');
            tmpMstTile.Append(len);

            return tmpMstTile.ToString();
        }
        #endregion

        #region 解包处理

        /// <summary>
        /// 解包操作
        /// </summary>
        /// <param name="msg"></param>
        /// <param name="returnData"></param>
        /// <returns></returns>
        public void DoAnalyze(Message msg, byte[] returnData)
        {
            try
            {
                //丢弃前8位
                var ret = new byte[returnData.Length - 8];
                Array.Copy(returnData, 8, ret, 0, ret.Length);
                returnData = ret;

                //报文前68位内容       
                byte[] msg60 = new byte[68];
                //报文数据区长度        
                int msgDataLen = 0;
                //报文数据区内容
                byte[] msgData;
                //报文有效数据内容
                byte[] msgDataReal;
                //报文位图区
                byte[] msgBit;
                string msgBitStr = "";

                //报文前60位（60位报文头）
                for (int i = 0; i < 68; i++)
                {
                    msg60[i] = returnData[i];
                }

                //报文数据区长度 
                byte[] tmpLen = new byte[4];
                Array.Copy(msg60, 64, tmpLen, 0, 4);
                msgDataLen = Convert.ToInt32(PlatformSettings.Encoding.GetString(tmpLen));

                //报文前60位字符串内容
                //MsgStr60 = Encoding.GetEncoding(CAppInfo.CodingStr).GetString(Msg60);

                #region 20140423 王全
                //承德平台无此返回报文场景
                ////如果报文数据区第五位为0xff
                ////总共报文数据区为4位应答码.
                //if (returnData[72] == (byte)'\0')
                //{
                //    //应答码错误信息
                //    byte[] tmpData = new byte[4];
                //    //取得应答码错误信息内容
                //    Array.Copy(returnData, 68, tmpData, 0, 4);
                //    //返回应答码
                //    msg.Fd12 = PlatformSettings.Encoding.GetString(tmpData);
                //    return;
                //}
                #endregion

                //取得报文数据区内容
                msgData = new byte[msgDataLen];
                Array.Copy(returnData, 68, msgData, 0, msgDataLen);
                //文件标志
                byte fileDataFlag = returnData[20];
                //解密数据区内容
                //MsgPackage.Encrypt(msgData, Encoding.ASCII.GetBytes(CommonSettings.KeyStr),
                //                   0);
                #region delete 解包封装
                ////报文数据区格式为 5位报文类型+16位位图区域+有效数据区
                ////报文位图区
                ////报文位图区存在2种情况，当位图区第1域为0时，位图长度为64（压缩为8位数据），否则为128（压缩为16位数据）
                ////标志位，是否采用128位位图
                //bool IsBitmap128 = Convert.ToString(msgData[5], 2).PadLeft(8, '0').StartsWith("1");

                //msgBit = new byte[IsBitmap128 ? 16 : 8];
                //Array.Copy(msgData, 5, msgBit, 0, msgBit.Length);
                ////扩展16位字符串转换为128位01格式的位图字符串
                //foreach (byte bytes in msgBit)
                //{
                //    msgBitStr += Convert.ToString(bytes, 2).PadLeft(8, '0');
                //}
                ////写调试日志
                ////MsgPackage.LogObj.Debug("\n返回位图:\n" + msgBitStr.Replace('\0', '\n'));
                ////报文数据内容
                //int startIndex = 5 + (IsBitmap128 ? 16 : 8);
                //msgDataReal = new byte[msgDataLen - startIndex];
                //Array.Copy(msgData, startIndex, msgDataReal, 0, msgDataReal.Length);
                ////写调试日志
                ////MsgPackage.LogObj.Debug("\n解包前应答数据:\n" + PlatformSettings.Encoding.GetString(msgDataReal).Replace('\0', '\n'));

                ////详细解析每个域的信息
                ////Message tmpMsg = AnilyzeFd(msgBitStr, msgDataReal, msg);
                //if (!msg.AnilyzeFd(msgBitStr, msgDataReal))
                //{
                //    //解包失败
                //    throw new FormatException("8583通讯解包操作失败！具体情况请查看日志！");
                //}
                if (!msg.AnilyzeFd(msgData))
                {
                    //解包失败
                    throw new FormatException("8583通讯解包操作失败！具体情况请查看日志！");
                }
                #endregion
                //将解析后结果复制到当前交易对象中
                //MsgPackage.Clone(msg, tmpMsg);
                //有文件附件的处理
                //存在附件，规则[文件名称:30][数据长度:8][数据:n]
                var fileLen = returnData.Length - 68 - msgDataLen - 38 - 1;
                if (fileLen > 0)
                {
                    //报文文件内容               
                    byte[] fileData = new byte[fileLen];
                    Array.Copy(returnData, 68 + msgDataLen + 38 + 1, fileData, 0, fileLen);
                    //返回解包后文件数据
                    msg.FileData = Message.Cconv(PlatformSettings.Encoding.GetString(fileData), false);//生僻字转义：文件解包处理
                    //写调试日志
                    PlatformLogger.CommunicationInfo("\n文件数据:\n" + PlatformSettings.Encoding.GetString(fileData));
                }
            }
            catch (Exception ex)
            {
                //写错误信息
                PlatformLogger.SystemErrorInfo("解析报文失败！", ex);
                throw;
            }
        }
        #endregion

    }
}
