using Edge.Core.Parser.BinaryParser.Attributes;
using Edge.Core.Parser.BinaryParser.Util;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;

namespace LanTian_Sinopec_PumpIcCardReader
{
    public class PumpNotifyTransactionDoneRequest : KaJiLianDongV11MessageTemplateBase
    {
        public override string ToLogString()
        {
            return base.ToLogString() + ", Friendly T_Type_交易类型:" + GetFriendlyT_Type_交易类型(this.T_Type_交易类型).Select(s => s.ToString()).Aggregate((acc, n) => acc + "--" + n);
        }

        //[Format(1, EncodingType.BIN, 0)]
        //public byte POS_P终端机身号 { get; set; }

        /// <summary>
        /// 每一个通讯终端内部必须有一个独立的递增的交易流水号 POS-TTC,从此通讯终端送出
        /// 的每笔交易流水号都必须不相同,而且是连续递增的;
        /// </summary>
        [Format(4, EncodingType.BIN, 1)]
        public int POS_TTC { get; set; }

        /// <summary>
        ///  b7=1:卡错; 
        ///        b6=0/1:使用后台黑(白)名单/使用油机内黑(白)名单
        ///        b4 = 1:扣款签名有效(无法判断用户卡 TAC 标记是否清除); 
        /// b3-b0:0=正常加油; 
        ///1=逃卡;  
        ///2=错卡; 
        ///3=补扣;  
        ///4=补充 
        ///5=员工上班(每条枪一条记录;对于一个IC卡终端有多条油枪时,每枪一条记录) 
        ///6=员工下班(每条枪一条记录;一个IC卡终端有多条油枪时,每枪一条记录) 
        ///7=非卡机联动加油 
        ///8=对油价信息的回应 
        ///9=卡片交易出错记录(出错后在TAC即电子签名字段填写出错原因,出错原因代码见附录9) 
        /// </summary>
        /// <param name="raw"></param>
        /// <returns></returns>
        public static IEnumerable<PumpTransactionType> GetFriendlyT_Type_交易类型(byte raw)
        {
            var result = new List<PumpTransactionType>();
            if (raw.GetBit(7) == 1) result.Add(PumpTransactionType.卡错);
            result.Add(raw.GetBit(6) == 0 ? PumpTransactionType.使用后台黑or白名单 : PumpTransactionType.使用油机内黑or白名单);
            if (raw.GetBit(4) == 1) result.Add(PumpTransactionType.扣款签名有效);
            var bit0To3 = raw & 15;
            switch (bit0To3)
            {
                case 0:
                    result.Add(PumpTransactionType.正常加油);
                    break;
                case 1:
                    result.Add(PumpTransactionType.逃卡);
                    break;
                case 2:
                    result.Add(PumpTransactionType.错卡);
                    break;
                case 3:
                    result.Add(PumpTransactionType.补扣);
                    break;
                case 4:
                    result.Add(PumpTransactionType.补充);
                    break;
                case 5:
                    result.Add(PumpTransactionType.员工上班);
                    break;
                case 6:
                    result.Add(PumpTransactionType.员工下班);
                    break;
                case 7:
                    result.Add(PumpTransactionType.非卡机联动加油);
                    break;
                case 8:
                    result.Add(PumpTransactionType.对修改油价信息的回应);
                    break;
                case 9:
                    result.Add(PumpTransactionType.卡片交易出错记录);
                    break;
            }
            return result.ToArray();
        }

        public enum PumpTransactionType
        {
            卡错,
            使用后台黑or白名单,
            使用油机内黑or白名单,
            扣款签名有效,
            正常加油,
            逃卡,
            错卡,
            补扣,
            补充,
            员工上班,
            员工下班,
            非卡机联动加油,
            对修改油价信息的回应,
            卡片交易出错记录
        }
        /// <summary>
        ///  call function GetFriendlyT_Type_交易类型() to get more friendly result.
        ///  交易类型 
        ///  b7=1:卡错; 
        ///  b6=0/1:使用后台黑(白)名单/使用油机内黑(白)名单 
        ///  b4=1:扣款签名有效(无法判断用户卡 TAC 标记是否清除); 
        ///  b3-b0:0=正常加油; 
        ///         1=逃卡; 
        ///         2=错卡; 
        ///         3=补扣; 
        ///         4=补充 
        ///         5=员工上班(每条枪一条记录;对于一个IC卡终端有多条油枪时,每枪一条记录) 
        ///         6=员工下班(每条枪一条记录;一个IC卡终端有多条油枪时,每枪一条记录) 
        ///         7=非卡机联动加油 
        ///         8=对油价信息的回应 
        ///         9=卡片交易出错记录(出错后在TAC即电子签名字段填写出错原因,出错原因代码见附录9) 
        /// </summary>
        [Format(1, EncodingType.BIN, 2)]
        public byte T_Type_交易类型 { get; set; }

        /// <summary>
        /// 日期及时间 
        /// </summary>
        [Format(7, EncodingType.BcdString, 3)]
        public string Raw_TIME { get; private set; }

        public DateTime TIME
        {
            get { return DateTime.Parse(this.Raw_TIME); }
            set { this.Raw_TIME = value.ToString("yyyyMMddHHmmss"); }
        }

        [Format(10, EncodingType.BcdString, 4)]
        public string ASN卡应用号 { get; set; }

        /// <summary>
        /// 正常成交:成交后余额; 
        /// 正常成交:成交后余额; 逃卡或卡错:交易前的原额,单位同UNIT的规定 。
        /// </summary>
        [Format(4, EncodingType.BIN, 5)]
        public int BAL余额 { get; set; }

        [Format(3, EncodingType.BIN, 6)]
        public int AMN数额 { get; set; }

        /// <summary>
        /// 卡交易序号 
        /// </summary>
        [Format(2, EncodingType.BIN, 7)]
        public int CTC { get; set; }

        /// <summary>
        /// 电子签名 ,  加油、补扣、补充交易时为TAC,逃卡时为GTAC 
        /// </summary>
        [Format(4, EncodingType.BIN, 8)]
        public int TAC电子签名 { get; set; }

        /// <summary>
        /// 解灰认证码 , 逃卡/卡错时有效 
        /// </summary>
        [Format(4, EncodingType.BIN, 9)]
        public int GMAC电子签名 { get; set; }


        /// <summary>
        /// 解灰认证码 , 逃卡/卡错时有效 
        /// </summary>
        [Format(4, EncodingType.BIN, 10)]
        public int PSAM_TAC灰锁签名 { get; set; }

        /// <summary>
        /// PSAM卡号,右8个字节用于PSAM-TAC的密钥分散算 法
        /// </summary>
        [Format(10, EncodingType.BcdString, 11)]
        public string PSAM_ASN_PSAM应用号 { get; set; }

        /// <summary>
        /// 用于TAC,GTAC运算 
        /// </summary>
        [EnumerableFormat(6, 12, EncodingType = EncodingType.BIN)]
        public List<byte> PSAM_TID_PSAM编号 { get; set; }

        /// <summary>
        ///  由PSAM卡产生的终端交易序号,签名以此为准
        /// </summary>
        [Format(4, EncodingType.BIN, 13)]
        public int PSAM_TTC { get; set; }

        /// <summary>
        ///  0=石油卡电子油票; 1=石油积分区积分; 2=金融卡电子钱包; 3=金融卡电子存折
        /// </summary>
        [Format(1, EncodingType.BIN, 14)]
        public byte DS_扣款来源 { get; set; }

        /// <summary>
        /// Bit1-0 (单位) =0:金额(分); =1:点数(0.01点) Bit7-4 (方式) =0:现金;  =1:油票; =2:记帐 =3:银行卡;=4:其他; =5:其他1
        /// </summary>
        [Format(1, EncodingType.BIN, 15)]
        public byte UNIT_结算单位_方式 { get; set; }

        /// <summary>
        /// b0= 0 = 石化规范卡;1 = PBOC金融卡; 
        /// </summary>
        [Format(1, EncodingType.BIN, 16)]
        public byte C_TYPE_卡类 { get; set; }

        /// <summary>
        /// b7-4:卡密钥索引号;b3-0:卡密钥版本号 
        /// </summary>
        [Format(1, EncodingType.BIN, 17)]
        public byte VER_版本 { get; set; }

        /// <summary>
        /// 
        /// </summary>
        [Format(1, EncodingType.BIN, 18)]
        public byte NZN_枪号 { get; set; }

        // Fu Ren Pump have the issue of pass in this code, at least in lab environment.
        [Format(2, EncodingType.BcdString, 19)]
        public string G_CODE_油品代码 { get; set; }

        //[Format(2, EncodingType.BIN, 19)]
        //public int G_CODE_油品代码 { get; set; }

        [Format(3, EncodingType.BIN, 20)]
        public int VOL_升数 { get; set; }

        [Format(2, EncodingType.BIN, 21)]
        public int PRC_成交价格 { get; set; }

        /// <summary>
        ///  255:没有员工上班
        /// </summary>
        [Format(1, EncodingType.BIN, 22)]
        public byte EMP_员工号 { get; set; }


        [Format(4, EncodingType.BIN, 23)]
        public int V_TOT_升累计 { get; set; }

        /// <summary>
        ///  全部填零
        /// </summary>
        [EnumerableFormat(11, 24, EncodingType = EncodingType.BIN)]
        public List<byte> RFU_备用 { get; set; }

        /// <summary>
        /// PBOC 标准3DES算法 计算范围:从POS-TTC开始(含POS-TTC)
        /// </summary>
        [Format(4, EncodingType.BIN, 25)]
        public int T_MAC_终端数据认证码 { get; set; }
    }
}