using Edge.Core.Parser.BinaryParser.Attributes;
using Edge.Core.Parser.BinaryParser.Util;
using Edge.Core.Parser.BinaryParser.MessageEntity;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace HengshanPaymentTerminal.MessageEntity
{
    public enum Command
    {
        /// <summary>
        /// Regular check command from pump against system.
        /// 加油机查询命令。
        /// </summary>
        Check_cmd = 0x10,

        /// <summary>
        /// Result of the check command.
        /// 查询命令的应答。
        /// </summary>
        Ver_info = 0x11,

        //*************************************************************

        /// <summary>
        /// Register terminal after power-on.
        /// 支付终端上电注册。
        /// </summary>
        RegisterRequest = 0x13,

        /// <summary>
        /// 后台回应支付终端上电注册。
        /// </summary>
        RegisterResult = 0x14,

        //*************************************************************

        /// <summary>
        /// Validate card from terminal to system.
        /// 验卡请求。
        /// </summary>
        ValidateCardRequest = 0x15,

        /// <summary>
        /// Validate card result from the system.
        /// 后台返回验卡结果。
        /// </summary>
        ValidateCardResult = 0x16,

        //*************************************************************

        AuthRequest = 0x17,
        AuthResult = 0x18,

        //*************************************************************

        /// <summary>
        /// Cancellation of authorization request from terminal to system.
        /// 支付终端发起撤销授权请求。
        /// </summary>
        CancelAuthRequest = 0x19,

        /// <summary>
        /// The system returns result of cancellation of auth.
        /// 后台返回撤销授权结果。
        /// </summary>
        CancelAuthResult = 0x1A,

        //*************************************************************

        ChangeAuthMode = 0x1B,
        ChangeAuthModeAck = 0x20,

        //*************************************************************

        FuelingData = 0x1C,
        FuelingDataResult = 0x35,

        //*************************************************************

        /// <summary>
        /// Change fuel price from system to pump.
        /// 改价命令。
        /// </summary>
        ChangePrice = 0x1E,

        /// <summary>
        /// Change fuel price result from pump to system.
        /// 油机返回改价结果。
        /// </summary>
        ChangePriceResult = 0x1F,

        //*************************************************************

        QueryGrayRecordRequest = 0x21,
        GrayRecord = 0x22,

        //*************************************************************

        ReadVolumeTotalizer = 0x23,
        VolumeTotalizerResult = 0x24,

        //*************************************************************

        DataRequest = 0x25,
        DataBytesLength = 0x26,
        DataContentRequest = 0x27,
        DataContent = 0x28,

        //*************************************************************

        DispenserInfoRequest = 0x29,
        DispenserInfo = 0x2A,

        //*************************************************************

        SendErrorInfoRequest = 0x2B,
        ErrorInfoAck = 0x2C,

        //*************************************************************

        TransactionData = 0x2D,
        TransactionDataAck = 0x32,

        //*************************************************************

        SystemAuth = 0x2E,
        SystemAuthResult = 0x31,

        OtherNonCardAuth = 0x2F,

        //*************************************************************

        /// <summary>
        /// Payment request from terminal.
        /// 终端发起支付请求，命令字30H。
        /// </summary>
        PaymentRequest = 0x30,
        PaymentData = 0x1D,

        //*************************************************************

        QueryTransactionInfo = 0x33,
        TransactionInfoResult = 0x34,

        //*************************************************************

        RecordCallback = 0x36,
        RecordCallbackAck = 0x37,

        //*************************************************************

        QueryTransactionData = 0x38,
        QueryTransactionDataAck = 0x39,

        //*************************************************************

        AuthManualCancel = 0x40,
        AuthManualCancelAck = 0x41,

        //*************************************************************

        EnableAuth = 0x42,
        EnableAuthAck = 0x43,

        //*************************************************************

        /// <summary>
        /// Lock or unlock a pump.
        /// 锁机或解锁命令。
        /// </summary>
        LockOrUnlockPump = 0x44,

        /// <summary>
        /// The result of locking or unlocking a pump.
        /// 锁机或解锁命令的回复。
        /// </summary>
        LockOrUnlockPumpAck = 0x45,

        //*************************************************************

        SystemOperationAck = 0x47,

        GetRfTagInfo = 0x46,

        VerifyFingerPrint = 0x48,

        ReturnTotalizer = 0x49
    }

    /// <summary>
    /// Enumeration of the calling parties, either pump or system
    /// 主叫方，加油机或后台
    /// </summary>
    public enum CallingParty
    {
        /// <summary>
        /// System/后台
        /// </summary>
        System,

        /// <summary>
        /// Pump/加油机，实际上是终端
        /// </summary>
        Pump
    }

    /// <summary>
    /// Base class of IC card terminal messages.
    /// IC卡终端与后台交互的消息，基类。
    /// </summary>
    public abstract class CardMessageBase : MessageTemplateBase
    {
        public CardMessageBase(Command handle)
        {
            //Handle = handle;
        }

        /// <summary>
        /// Get the caller (Frame sequence number bit 6 indicates the calling party, 0 = system, 1 = pump)
        /// 获取主叫方。命令/数据帧号，第6个bit，0 = 后台， 1 = 加油机
        /// </summary>
        public CallingParty Caller
        {
            get
            {
                if (FrameSqNoByte.GetBit(6) == 1)
                    return CallingParty.Pump;
                return CallingParty.System;
            }
        }

        /// <summary>
        /// Static field, 'FA'
        /// 数据包头，长度1字节，Hex “FA”
        /// </summary>
        [Format(1, EncodingType.BIN, -100)]
        public virtual byte Prefix { get; set; }

        /// <summary>
        /// The destination address this message targets.
        /// 目标地址，长度1字节
        /// </summary>
        [Format(1, EncodingType.BIN, -99)]
        public virtual byte DestinationAddress { get; set; }

        /// <summary>
        /// The source address of the message.
        /// 源地址，长度1字节
        /// </summary>
        [Format(1, EncodingType.BIN, -98)]
        public virtual byte SourceAddress { get; set; }

        /// <summary>
        /// Command/Data frame sequence number.
        /// 命令/数据帧号
        /// 格式：
        /// b7=0；b6=0时，后台主叫，b6=1，油机主叫；
        /// b5~b0为帧号，主叫方每发送一新帧，此帧号加一，应答方回送此帧号。
        /// </summary>
        [Format(1, EncodingType.BIN, -97)]
        public virtual byte FrameSqNoByte { get; set; }

        /// <summary>
        /// The frame number is in the FrameSqNoByte bit 5 to bit 0 (6 bits).
        /// 帧号为 命令/数据帧号 字节的b5-b0，共6个bit。
        /// </summary>
        public virtual int FrameNo
        {
            get { return FrameSqNoByte & 0x3F; }
        }

        /// <summary>
        /// Set the calling party of the message
        /// 设置此消息的主叫方
        /// </summary>
        /// <param name="party"></param>
        public void SetCallingParty(CallingParty party)
        {
            FrameSqNoByte = FrameSqNoByte.SetBit(6, 6, party == CallingParty.Pump ? 1 : 0);
        }

        public void SetSeqNo(byte sqNo)
        {
            // sequence number is max 5 bits.
            if (sqNo > 63)
                throw new ArgumentOutOfRangeException("maximum sequenceNumber is 63(total 6 bits).");
            var debug = FrameSqNoByte >> 6 << 6;
            FrameSqNoByte = (byte)(debug + sqNo);
        }

        /// <summary>
        /// Length of message body
        /// 有效数据长度，2字节，HEX
        /// </summary>
        [Format(2, "%OnSerializingBytesCount", EncodingType.BIN, -96)]
        public virtual int BodyLength { get; set; }

        /// <summary>
        /// Command type
        /// 命令字
        /// </summary>
        [Format(1, EncodingType.BIN, -95)]
        public byte Handle { get; set; }

        /// <summary>
        /// The meaningful body of the message.
        /// 消息有效数据
        /// </summary>
        //[EnumerableFormat("BodyLength", "-2", 2, EncodingType = EncodingType.BIN)]
        //public List<byte> Body { get; set; }

        //[Format(1, EncodingType.BIN, -1)]
        public byte ETX { get; set; }

        /// <summary>
        /// CRC of the whole message skipping additional 'FA'
        /// 消息的CRC校验，转义'FA'字节不计入
        /// </summary>
        [EnumerableFormat(2, 1000, EncodingType = EncodingType.BIN)]
        public virtual List<byte> CRC { get; set; }

        public override string ToLogString()
        {
            return GetType().Name + "    " + base.ToLogString().Replace(
                "FrameSqNoByte:", "(Caller: " + Caller + ", FrameNo: " + FrameNo + ")FrameSqNoByte:");
        }

        /// <summary>
        /// 将数据转成数据对象
        /// </summary>
        /// <param name="datas">数据</param>
        /// <returns></returns>
        public override MessageTemplateBase ToObject(byte[] datas)
        {
            return this;
        }

        /// <summary>
        /// 将数据对象转为数组
        /// </summary>
        /// <returns></returns>
        public override byte[] ToCommonByteArray()
        {
            return new byte[0];
        }
    }
}
