package com.mq.mylibrary.tool;

import android.util.Base64;
import android.util.Log;

import com.mq.mylibrary.CardData;
import com.mq.mylibrary.base.BaseCard;

import java.io.InputStream;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.util.Timer;
import java.util.TimerTask;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import cn.pda.rfid.hf.HfConmmand;
import cn.pda.rfid.hf.HfError;
import cn.pda.rfid.hf.HfReader;
import cn.pda.serialport.Main;

/**
 * 创建人 mQ
 * 创建时间 2019/10/31 0031 17:36
 * 文件名称 RFIDTool
 * 说明:
 **/
public class RFIDTool implements BaseCard {


    private RFIDTool() {
    }

    private static class Helper {
        private static final RFIDTool instance = new RFIDTool();
    }

    public static RFIDTool get() {
        return Helper.instance;
    }

    private Timer timer;
    private TimerTask timerTask;
    private final int TOTAL_SECONDS = 10;
    private int remainSeconds = TOTAL_SECONDS;
    private int loopTimes = 0;//循环次数

    private void cancelTimer() {
        if (timer != null) {
            timer.cancel();
            timer = null;
        }
        remainSeconds = TOTAL_SECONDS;
        loopTimes = 0;
    }

    private int authICCard(HfConmmand hf, byte[] uid, HfError error, int i) {
        return hf.auth14443A(HfReader.AUTH_A, Tools.HexString2Bytes("FFFFFFFFFFFF"), uid, i * 4, error);
    }

    @Override
    public void open() {
        Main.initSerialPort();
    }

    @Override
    public void close() {
        Main.destroy();//关闭串口
    }

    @Override
    public CardData readCard() {
        HfError error = new HfError();
        CardData result = new CardData();
        HfConmmand hf = Main.getHf();
        InputStream is = Main.getIs();
        OutputStream os = Main.getOs();
        byte[] uid = hf.findCard14443A(error);
        if (uid == null) {
            result.state = "3";
            result.msg = "没有检测到IC卡，请重试！";
            cancelTimer();
            return result;
        }
        result.state = "0";
        if (is != null && os != null) {
            try {
                String strRead = "";
                StringBuilder sb = new StringBuilder();
                for (int i = 0; i < 16; i++) {
                    if (hf.auth14443A(HfReader.AUTH_A, Tools.HexString2Bytes("FFFFFFFFFFFF"), uid, i * 4, error) == 0) {
                        for (int j = i * 4; j < i * 4 + 3; j++) {
                            if (j != 0) {
                                byte[] readData = hf.read14443A(j, error);
                                if (readData != null) {
                                    Log.i("zhicang", "readData" + readData.length);
                                    strRead = new String(readData, "gb2312");
                                    Log.i("x_log", (j + 1) + ":" + strRead);
                                    if (strRead.contains("*")) {
                                        sb.append(strRead.substring(0, strRead.indexOf("*")));
                                    } else if ("0000000000000000".equals(strRead)) {
                                        break;
                                    } else {
                                        sb.append(strRead);
                                    }
                                }
                            }
                        }
                    } else {
                        Log.i("zhicang", "auth return false");
                    }
                }
                byte b[] = Base64.decode(sb.toString().getBytes(), Base64.DEFAULT);
                String cardInfo = new String(b, "gb2312");
                cancelTimer();
                result.resultData = cardInfo;
                LogTool.i("读取结果:" + cardInfo);
                return result;
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
                cancelTimer();
                result.state = "3";
                result.msg = "读卡失败";
                return result;
            } catch (IllegalArgumentException e1) {
                e1.printStackTrace();
                if (timer == null) {
                    timer = new Timer();
                    timerTask = new TimerTask() {
                        @Override
                        public void run() {
                            remainSeconds--;
                        }
                    };
                    timer.schedule(timerTask, 0, 1000);//立即执行 1秒执行一次
                }
                if (remainSeconds > 0) {
                    loopTimes++;
                    Log.i("timer", loopTimes + "");
                    return readCard();
                } else {
                    cancelTimer();
                    result.state = "4";
                    result.msg = "读卡失败";
                    return result;
                }
            }
        }
        cancelTimer();
        result.state = "4";
        result.msg = "读卡失败";
        return result;
    }

    @Override
    public String writeCard(String newCardInfo) {
        String tag = "";
        HfError error = new HfError();
        HfConmmand hf = Main.getHf();
        byte[] uid = hf.findCard14443A(error);
        if (uid == null) {
            tag = "请重新放卡";
            return tag;
        }
        Log.d("newCardInfo:", newCardInfo);
        try {
            byte[] b = newCardInfo.getBytes("gb2312");
            String encReadData = Base64.encodeToString(b, Base64.DEFAULT);//加密后的数据
            String newEncReadData = encReadData + "*";//加密字符串+特殊字符生成新的字符串 写入块中
            Log.d("newEncReadData:", newEncReadData);
            Pattern p = Pattern.compile("\\s*|\t|\r|\n");
            Matcher m = p.matcher(newEncReadData);
            newEncReadData = m.replaceAll("");
            int encLengs = newEncReadData.length();//加密后字符串长度
            Log.d("encLengs:", String.valueOf(encLengs));
            int count = encLengs / 16;//根据加密数据长度计算循环次数 4/16
            int remainLen = encLengs % 16;
            boolean flag = true;
            String encodeData = "";//每个块写入的数据
            int k = 0;
            for (int i = 0; i < 16; i++) {
                Log.d("i:", String.valueOf(i));
                int result = authICCard(hf, uid, error, i);//认证卡信息
                Log.d("result:", String.valueOf(result));
                while (result != 0) {
                    uid = hf.findCard14443A(error);
                    result = authICCard(hf, uid, error, i);//认证卡信息
                }
                if (result == 0) {
                    for (int j = i * 4; j < i * 4 + 3; j++) {
                        if (j != 0) {
                            //截取加密字符串
                            if (count == 0 && j == 1) {//写入的数据不够16位,差值补0
                                flag = false;
                                encodeData = newEncReadData.substring(0, remainLen);
                                for (int x = 0; x < 16 - remainLen; x++) {
                                    encodeData += "0";
                                }
                            } else if (k < count) {//如果写入字符超过16位，整除的部分肯定够截取16位
                                encodeData = newEncReadData.substring(k * 16, k * 16 + 16);
                            } else if (flag && remainLen != 0) {//如果写入字符有余数，有且只执行一次方法
                                flag = false;
                                encodeData = newEncReadData.substring(k * 16, k * 16 + remainLen);
                                for (int x = 0; x < 16 - remainLen; x++) {
                                    encodeData += "0";
                                }
                            } else {//上述所有条件不满足后，全部补0
                                encodeData = "0000000000000000";
                            }
                            k++;
                            Log.d("encodeData:", encodeData);
                            Log.d("encodeData.getBytes:", String.valueOf(encodeData.getBytes("gb2312")));
                            Log.d("j:", String.valueOf(j));
                            hf.write14443A(encodeData.getBytes("gb2312"), j, error);
                        }
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            tag = "写入失败，请重新放卡";
        }
        hf.halt();
        return tag;
    }

    /**
     * 清空IC卡
     */
    @Override
    public String clearCard() {
        String tag = "";
        HfError error = new HfError();
        HfConmmand hf = Main.getHf();
        byte[] uid = hf.findCard14443A(error);
        if (uid == null) {
            tag = "请重新放卡";
            return tag;
        }
        try {
            String encodeData = "0000000000000000";
            for (int i = 0; i < 16; i++) {
                Log.d("i:", String.valueOf(i));
                int result = authICCard(hf, uid, error, i);//认证卡信息
                Log.d("result:", String.valueOf(result));
                while (result != 0) {
                    uid = hf.findCard14443A(error);
                    result = authICCard(hf, uid, error, i);//认证卡信息
                }
                if (result == 0) {
                    for (int j = i * 4; j < i * 4 + 3; j++) {
                        if (j != 0) {
                            Log.d("encodeData:", encodeData);
                            Log.d("encodeData.getBytes:", String.valueOf(encodeData.getBytes("gb2312")));
                            Log.d("j:", String.valueOf(j));
                            hf.write14443A(encodeData.getBytes("gb2312"), j, error);
                        }
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            tag = "写入失败，请重新放卡";
        }
        hf.halt();
        return tag;
    }


}
