using log4net;
using OnlineStore.Common;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Asa.RFID
{
    public class RFID
    {
        public static readonly ILog LOGGER = LogManager.GetLogger("TheRFID");

        private string IP = "";
        private byte addr;
        private int portIndex;
        private bool IsConnect = false;
        private byte[] lastData = new byte[8];
        internal byte[] _buff;   //8字节缓存
        private byte[] _uid;    //卡片ID 
        public bool IsExist = false;
         
        public int ErrCode  = 0;
  
        public RFID(string ip)
        {
            this.IP = ip;
        }

        public int Close()
        {
            try
            {
                IsConnect = false;
                int ErrCode = ReaderA.StaticClassReaderA.CloseNetPort(portIndex);
                LOGGER.Info("Close RFID [" + IP + "]:" + ErrCode);
                return ErrCode;
            }
            catch (Exception e)
            {
                LOGGER.Error("Close RFID[" + IP + "] has error", e);
            }
            return -1;
        }


        public int Open()
        {
            if (IsConnect)
            {
                LOGGER.Warn(" RFID [" + IP + "] is already connected, no need to start again");
                return 0;
            }
            //IP合法
            string pattern = @"^((2[0-4]\d|25[0-5]|[01]?\d\d?)\.){3}(2[0-4]\d|25[0-5]|[01]?\d\d?)$";
            bool rtn = System.Text.RegularExpressions.Regex.IsMatch(IP, pattern);
            if (!rtn)
            {
                LOGGER.Error(IP + " is error");
                return -1;
            }

            string[] arr = IP.Split('.');
            if (arr.Length != 4)
            {
                LOGGER.Error(IP + " length is not 4");
                return -1;
            }
            addr = Convert.ToByte(arr[3]);
            int port = 6000 + Convert.ToInt32(arr[3]);
            portIndex = 0;

            int ErrCode = ReaderA.StaticClassReaderA.OpenNetPort(port, IP, ref addr, ref portIndex);
            LOGGER.Info("Connect [" + IP + "] :" + ErrCode);
            return ErrCode;
        }

        /// <summary>
        /// 查找电子标签,扫描模式不能使用
        /// </summary>
        /// <returns></returns>
        public bool FindRFID()
        {
            //0 不带AFI
            //1 带AFI
            //2 不带AFI,继续查询
            //3 带AFI,继续查询
            //6 不带AFI,新的查询
            //7 带AFI,新的查询
            byte state = 0;

            //Select模式需要AFI
            byte AFI = 0;

            //输出,1字节DSFID,8字节UID
            byte[] DSFIDAndUID = new byte[9];

            //输出,标签数量
            byte cardNumber = 0;

            ErrCode = ReaderA.StaticClassReaderA.Inventory(ref addr, ref state, ref AFI, DSFIDAndUID, ref cardNumber, portIndex);
            if (ErrCode == 0)
            {
                //查询时间
                //fCmdRet = StaticClassReaderA.GetInventoryTime(ref n_time, portIndex);
                Array.Copy(DSFIDAndUID, 1, _uid, 0, 8);
                IsExist = true;
                return true;
            }
            else
            {
                for (int i = 0; i < _uid.Length; i++)
                    _uid[i] = 0;
                IsExist = false;
                return false;
            }
        }

        public byte[] Read(bool isNeedFind = false )
        {
            if (isNeedFind)
            {
                FindRFID();
            }
            if (IsExist)
            {
                ReadRFID();
                return _buff;
            }
            return null;
        } 
        private void ReadRFID()
        {
            //0 不带AFI
            //1 带AFI
            //2 不带AFI,继续查询
            //3 带AFI,继续查询
            //6 不带AFI,新的查询
            //7 带AFI,新的查询
            byte state = 0; 
            //起始块号
            byte blockNum = 0; 
            //块数量
            byte blockCount = 2; 
            //输出,块内安全信息,长度为BlockCount个字节
            byte[] blockSecStatus = new byte[blockCount];  
            //输出,块内数据信息,长度为块的大小(4或8字节)乘以BlockCount个字节
            byte[] data = new byte[4 * blockCount];

            //错误代码
            byte errorCode = 0;

            ErrCode = ReaderA.StaticClassReaderA.ReadMultipleBlock(ref addr, ref state, _uid, blockNum, blockCount, blockSecStatus, data, ref errorCode, portIndex);
            if (ErrCode == 0)
            {
                Array.Copy(data, 0, _buff, 0, data.Length);
            }
        }
         
        private string byteToStr(byte[] data, int len)
        {
            string s = "";
            for (int i = 0; i < len; i++)
            {
                s += data[i].ToString("X2") + " ";
            }
            return s;
        }
    }
}