package com.hh.lib_cpu_card;

import android.content.Context;
import android.text.TextUtils;

import com.donsee.devices.CardReader;
import com.donsee.devices.HexUtil;
import com.hh.lib_base.BaseApplication;
import com.hh.lib_cpu_card.bean.DxApduResultBean;
import com.hh.lib_cpu_card.bean.ErrorCode;
import com.hh.lib_dx_base_multi.DxCardReader;
import com.hh.lib_dx_base_multi.DxInitListener;
import com.hh.lib_dx_base_multi.serialport.DxSerialportCardReader;
import com.hh.lib_dx_base_multi.serialport.listener.ReadCPUCardListener;

import java.util.ArrayList;

/**
 *
 * @author xwh
 * time 2024/9/13
 *  Description: CPU卡
 **/
public class DXCPUCardReader {

    private static volatile DXCPUCardReader instance = null;
    private NFCCardConfig config; //CPU卡配置
    private NFCCardResultListener nfcCardResultListener; //CPU卡回调监听

    private volatile String oldNFCResetInfo = "-2"; //上一次卡片信息，用于同卡间隔
    private volatile long recordTime = 0L;   //上一次读卡时间，用于同卡间隔

    private final int SUCCESS = 0; //读卡器操作时状态 >=0 成功;
    private final byte SAM1 = 0x11; //SAM1
    private final byte SAM2 = 0x12; //SAM2

    public DXCPUCardReader(Context context, NFCCardConfig config) {
        this.config = config;
        init(context);
    }

    /**
     *
     * @author xwh
     * Time 2024/11/5
     * Description: 初始化
     *
    **/
    public void init(Context context) {
        switch (DxSerialportCardReader.getInstance().getStatusEnum()){
            case SUCCESS:
                if (nfcCardResultListener != null) {
                    nfcCardResultListener.onInitSuccessState(true);
                    nfcCardResultListener.onLogInfo("NFC-CPU卡  初始化串口成功！");
                }
                DxSerialportCardReader.getInstance().setCpuCardListener(cpuCardListener);
                return;
            case  FAIL:
                if(nfcCardResultListener !=null){
                    nfcCardResultListener.onInitSuccessState(false);
                }
                DxSerialportCardReader.getInstance().setCpuCardListener(null);
                return;
            case DEFAULT:
                break;
        }
        initReader(context);
    }
    /**
     *
     * @author xwh
     * Time 2024/11/5
     * Description: 初始化读卡器
     *
    **/
    private void initReader(Context context){
        DxSerialportCardReader.getInstance().init(context, DXCPUCardReader.class.getName(), new DxInitListener() {
            @Override
            public void onLogInfo(String msg) {

            }

            @Override
            public void initSuccess() {
                if (nfcCardResultListener != null) {
                    nfcCardResultListener.onInitSuccessState(true);
                    nfcCardResultListener.onLogInfo("NFC-CPU卡  初始化串口成功！");
                }
                DxSerialportCardReader.getInstance().setCpuCardListener(cpuCardListener);
            }

            @Override
            public void initFailed(String code, String msg) {
                if(nfcCardResultListener !=null){
                    nfcCardResultListener.onInitSuccessState(false);
                    nfcCardResultListener.onLogInfo(msg);
                }
                DxSerialportCardReader.getInstance().setCpuCardListener(null);
            }
        });
    }


    ReadCPUCardListener cpuCardListener =new ReadCPUCardListener() {
        @Override
        public void readNFC() {
            readCPUCard();
        }
    };


    public void setConfig(NFCCardConfig config) {
        this.config = config;
    }


    /**
     *
     * @author xwh
     * Time 2024/11/7
     * Description: 启动东信读卡器循环读取线程
     * TODO 此线程是一个东线串口读卡器总线程
    **/
    public boolean startRead(){
        if(DxSerialportCardReader.getInstance().isInitSuccessed()) {
            DxSerialportCardReader.getInstance().startRead();
            return true;
        }
        return false;
    }
    /**
     *
     * @author xwh
     * Time 2024/11/7
     * Description: 停止东信读卡器循环读取线程
     * TODO 此线程是一个东线串口读卡器总线程
     *
    **/
    public boolean stopRead(){
        if(DxSerialportCardReader.getInstance().isInitSuccessed()) {
            DxSerialportCardReader.getInstance().stopRead();
            return true;
        }
        return false;
    }


    /**
     * desc:获取单次CPU卡片信息
     *
     * @author xia weihao
     * @date 2024/6/27
     */
    public String getOnceCardInfo() {
        byte[] uid = new byte[10];
        byte type = (byte) 0x41; //0x41 表示TypeA/M1卡选卡,  0x43表示TypeB卡选卡
        byte[] chResponse = new byte[2048];
        CardReader cardReader=DxSerialportCardReader.getInstance().getCardReader();
        if (cardReader == null) {
            if(nfcCardResultListener !=null) {
                nfcCardResultListener.onLogInfo("getOnceCardInfo：cardReader = null");
            }
            return ErrorCode.ERROR_1;
        }
        long ret = cardReader.Donsee_ICRequest();
        if (ret != SUCCESS) {
            if(nfcCardResultListener !=null) {
                nfcCardResultListener.onLogInfo("TypeA寻卡失败: " + CardReader.getErrorMessage(ret));
            }
            return ErrorCode.ERROR_2;
        }
        if (cardReader.Donsee_ICAnticoll(uid) < SUCCESS) {
            if(nfcCardResultListener !=null) {
                nfcCardResultListener.onLogInfo("TypeA防碰撞失败: " + CardReader.getErrorMessage(ret));
            }
            return ErrorCode.ERROR_3;
        }
        ret = cardReader.Donsee_ICSelect(type);
        if (ret != SUCCESS) {
            if(nfcCardResultListener !=null) {
                nfcCardResultListener.onLogInfo("TypeA选卡失败 : " + CardReader.getErrorMessage(ret));
            }
            return ErrorCode.ERROR_4;
        }
        ret = cardReader.Donsee_PowerOnTypeA(chResponse);
        if (ret > SUCCESS) {
            return HexUtil.bytesToHex(chResponse, (int) ret);
        } else {
            if(nfcCardResultListener !=null) {
                nfcCardResultListener.onLogInfo("TypeA上电失败：" + CardReader.getErrorMessage(ret));
            }
            return ErrorCode.ERROR_5;

        }
    }

    /**
     * desc:发送指令
     * @param command      指令  测试  0084000008
     * @param type         1-CPU卡命令，2-PSAM卡命令
     * @param slot         PSAM卡选择卡槽
     * @author xia weihao
     * @date 2024/6/27
     */
    public String sendAPDU(int slot, String command, int type) {
        CardReader cardReader=DxSerialportCardReader.getInstance().getCardReader();
        if (cardReader == null) {
            nfcCardResultListener.onLogInfo("sendAPDU：cardReader = null");
            return ErrorCode.ERROR_1;
        }
        byte[] chResponse = new byte[2048];
        long ret;
        byte cardSlot = SAM1; //SAM1
        if (slot == 2) {
            cardSlot = SAM2;//SAM2
        }
        if (type == 2) {
            ret = cardReader.Donsee_PowerOn_APDU(cardSlot, HexUtil.hexToBytes(command), chResponse);//接触执行apdu
            if (ret > SUCCESS) {
                return HexUtil.bytesToHex(chResponse, (int) ret);
            } else {
                if(nfcCardResultListener !=null) {
                    nfcCardResultListener.onLogInfo("接触卡执行APDU失败：" + CardReader.getErrorMessage(ret));
                }
                return ErrorCode.ERROR_2;
            }

        } else {
            ret = cardReader.Donsee_APDU(HexUtil.hexToBytes(command), chResponse);//非接执行apdu
            if (ret > SUCCESS) {
                return HexUtil.bytesToHex(chResponse, (int) ret);
            } else {
                if(nfcCardResultListener !=null) {
                    nfcCardResultListener.onLogInfo("非接卡执行APDU失败：" + CardReader.getErrorMessage(ret));
                }
                return ErrorCode.ERROR_2;
            }
        }
    }

    /**
     * desc:执行数组指令
     * @param commandApdus      指令集  测试  0084000008
     * @param type         1-CPU卡命令，2-PSAM卡命令
     * @param slot         PSAM卡选择卡槽
     * @author xia weihao
     * @date 2024/6/27
     */
    public DxApduResultBean sendAPDU(int slot, ArrayList<String> commandApdus, int type) {
        synchronized (DXCPUCardReader.class) {
            DxApduResultBean resaultBean=new DxApduResultBean();
            CardReader cardReader=DxSerialportCardReader.getInstance().getCardReader();
            if (cardReader == null) {
                if(nfcCardResultListener !=null) {
                    nfcCardResultListener.onLogInfo("sendAPDU：cardReader = null");
                }
                resaultBean.setCode(ErrorCode.ERROR_1);
                resaultBean.setSuccess(false);
                return resaultBean;
            }
            byte[] chResponse = new byte[2048];
            long ret=0;
            byte cardSlot = SAM1; //SAM1
            if (slot == 2) {
                cardSlot = SAM2;//SAM2
            }
            ArrayList<String> resultInfo=new ArrayList<>();
            if (type == 2) {
                String command="";
                for (int i=0;i<commandApdus.size();i++){
                    command=commandApdus.get(i);
                    ret = cardReader.Donsee_PowerOn_APDU(cardSlot, HexUtil.hexToBytes(command), chResponse);//接触执行apdu
                    if(ret > SUCCESS){
                        String respose=HexUtil.bytesToHex(chResponse, (int) ret);
                        if (!TextUtils.isEmpty(respose) &&
                                respose.length() >= 4 &&
                                respose.endsWith(ErrorCode.APDU_SUCCESS)) { //9000 正常 成功执行
                            resaultBean.getResultInfo().add(HexUtil.bytesToHex(chResponse, (int) ret));
                        }else{
                            resaultBean.setCode(ErrorCode.ERROR_100);
                            resaultBean.setSuccess(false);
                            resaultBean.getResultInfo().add(HexUtil.bytesToHex(chResponse, (int) ret));
                            return resaultBean;
                        }
                    }else{
                        if(nfcCardResultListener !=null) {
                            nfcCardResultListener.onLogInfo("接触卡执行APDU失败：" + CardReader.getErrorMessage(ret));
                        }
                        resaultBean.setCode(ErrorCode.ERROR_2);
                        resaultBean.setSuccess(false);
                        return resaultBean;
                    }
                }

                resaultBean.setSuccess(true);
                resaultBean.setCode(ErrorCode.SUCCESS);
                return resaultBean;
            } else {
                String command="";
                for (int i=0;i<commandApdus.size();i++){
                    command=commandApdus.get(i);
                    ret = cardReader.Donsee_APDU(HexUtil.hexToBytes(command), chResponse);//非接执行apdu
                    if(ret > SUCCESS){
                        String respose=HexUtil.bytesToHex(chResponse, (int) ret);
                        if (!TextUtils.isEmpty(respose) &&
                                respose.length() >= 4 &&
                                respose.endsWith(ErrorCode.APDU_SUCCESS)) { //9000 正常 成功执行
                            resaultBean.getResultInfo().add(HexUtil.bytesToHex(chResponse, (int) ret));
                        }else{
                            resaultBean.setCode(ErrorCode.ERROR_100);
                            resaultBean.setSuccess(false);
                            resaultBean.getResultInfo().add(HexUtil.bytesToHex(chResponse, (int) ret));
                            return resaultBean;
                        }
                    }else{
                        if(nfcCardResultListener !=null) {
                            nfcCardResultListener.onLogInfo("非接卡执行APDU失败：" + CardReader.getErrorMessage(ret));
                        }
                        resaultBean.setCode(ErrorCode.ERROR_2);
                        resaultBean.setSuccess(false);
                        return resaultBean;
                    }
                }

                resaultBean.setSuccess(true);
                resaultBean.setCode(ErrorCode.SUCCESS);
                return resaultBean;
            }
        }
    }

    /**
     *
     * @author xwh
     * Time 2024/11/7
     * Description: 冷复位
     *
    **/
    public String coldReset(int slot){
        CardReader cardReader=DxSerialportCardReader.getInstance().getCardReader();
        if (cardReader == null) {
            if(nfcCardResultListener !=null) {
                nfcCardResultListener.onLogInfo("coldReset：cardReader = null");
            }
            return ErrorCode.ERROR_1;
        }
        byte[] chResponse = new byte[2048];
        long ret;
        byte cardSlot = 0x11; //SAM1
        if(slot==2){
            cardSlot=0x12;//SAM2
        }
        ret = cardReader.Donsee_ColdPowerOn(cardSlot, chResponse);
        if (ret > SUCCESS) {
            return HexUtil.bytesToHex(chResponse, (int) ret);
        } else {
            if(nfcCardResultListener !=null) {
                nfcCardResultListener.onLogInfo("冷复位失败：" + CardReader.getErrorMessage(ret));
            }
            return ErrorCode.ERROR_2;
        }
    }

    /**
     * desc:设置蜂鸣时间
     *
     * @param time 设置蜂鸣时间 time 建议填50
     * @author xia weihao
     * @date 2024/6/27
     */
    public boolean startBeep(int time) {
        CardReader cardReader=DxSerialportCardReader.getInstance().getCardReader();
        if (cardReader == null) {
            if(nfcCardResultListener !=null) {
                nfcCardResultListener.onLogInfo("startBeep：cardReader = null");
            }
            return false;
        }
        long ret = cardReader.Donsee_Beep(time);
        if (ret == SUCCESS) {
            return true;
        } else {
            return false;
        }
    }


    /**
     *
     * @author xwh
     * Time 2024/11/7
     * Description: CPU卡循环读取
     *
    **/
    private void readCPUCard() {
        byte[] uid = new byte[10];
        byte type = (byte) 0x41; //0x41 表示TypeA/M1卡选卡,  0x43表示TypeB卡选卡
        byte[] chResponse = new byte[2048];
        CardReader cardReader=DxSerialportCardReader.getInstance().getCardReader();
        if (cardReader == null) {
            resetSameCardState();
            if(nfcCardResultListener !=null) {
                nfcCardResultListener.onLogInfo("readNFC cardReader = null");
                if(config != null&&config.isComeBackFailed()){
                    nfcCardResultListener.onCardSearchFailed();
                }
            }
            return;
        }
        long ret = cardReader.Donsee_ICRequest();
        if (ret != SUCCESS) {
            resetSameCardState();
            if(nfcCardResultListener !=null) {
                nfcCardResultListener.onLogInfo("TypeA寻卡失败: " + CardReader.getErrorMessage(ret));
                if(config != null&&config.isComeBackFailed()){
                    nfcCardResultListener.onCardSearchFailed();
                }
            }
            return;
        }
        if (cardReader.Donsee_ICAnticoll(uid) < SUCCESS) {
            resetSameCardState();
            if(nfcCardResultListener !=null) {
                nfcCardResultListener.onLogInfo("TypeA防碰撞失败: " + CardReader.getErrorMessage(ret));
                if(config != null&&config.isComeBackFailed()){
                    nfcCardResultListener.onCardSearchFailed();
                }
            }
            return;
        }
        ret = cardReader.Donsee_ICSelect(type);
        if (ret != SUCCESS) {
            resetSameCardState();
            if(nfcCardResultListener !=null) {
                nfcCardResultListener.onLogInfo("TypeA选卡失败 : " + CardReader.getErrorMessage(ret));
                if(config != null&&config.isComeBackFailed()){
                    nfcCardResultListener.onCardSearchFailed();
                }
            }
            return;
        }
        ret = cardReader.Donsee_PowerOnTypeA(chResponse);
        if (ret > SUCCESS) {
            String info = HexUtil.bytesToHex(chResponse, (int) ret);
            //todo 同卡在间隔时间内不重复推送逻辑
            long currTime = System.currentTimeMillis();
            long intervalTime = 0L;
            if (config != null && config.getSameCardIntervalTime() > 0) {
                intervalTime = config.getSameCardIntervalTime();
            }
            if (info.equals(oldNFCResetInfo) && currTime > 0) {
                // todo 当同卡间隔时间大于intervalTime，重置字段并发送一次数据
                if (currTime - recordTime > intervalTime) {
                    oldNFCResetInfo = info;
                    recordTime = currTime;
                    if(nfcCardResultListener !=null) {
                        nfcCardResultListener.onPollingInfo(info);
                    }
                }
            } else {
                oldNFCResetInfo = info;
                recordTime = currTime;
                if(nfcCardResultListener !=null) {
                    nfcCardResultListener.onPollingInfo(info);
                }
            }

        } else {
            resetSameCardState();
            if(nfcCardResultListener !=null) {
                nfcCardResultListener.onLogInfo("TypeA上电失败：" + CardReader.getErrorMessage(ret));
                if(config != null&&config.isComeBackFailed()){
                    nfcCardResultListener.onCardSearchFailed();
                }
            }
        }
    }


    /**
     *
     * desc：重置同卡间隔逻辑状态
     * @author xia weihao
     * @date 2024/6/27
     *
     */
    private void resetSameCardState(){
        oldNFCResetInfo = "";
        recordTime = 0;
    }

    public void setNfcCardResultListener(NFCCardResultListener nfcCardResultListener) {
        this.nfcCardResultListener = nfcCardResultListener;
    }

    /**
     *
     * @author xwh
     * Time 2024/9/13
     * Description: 销毁资源
     *
    **/
    public void release() {
        DxSerialportCardReader.getInstance().setCpuCardListener(null);
        DxSerialportCardReader.getInstance().release();
        instance = null;

    }


    public interface NFCCardResultListener {
        //初始化是否成功
        void onInitSuccessState(boolean isSuccess);
        //循环,获取卡片信息
        void onPollingInfo(String info);
        //循环，返回寻卡失败
        void onCardSearchFailed();
        //NFC卡公共错误信息
        void onLogInfo(String errMsg);


    }

    //提供一个公共的访问方法，用于获取该类的唯一实例
    public static DXCPUCardReader getInstance(NFCCardConfig config) {
        //如果instance为空，就进行实例化
        if (instance == null) {
            //保证多线程下只有一个线程进行实例化
            synchronized (DXCPUCardReader.class) {
                //第二次判断，避免多线程下创建多个实例
                if (instance == null) {
                    instance = new DXCPUCardReader(BaseApplication.getContext(),config);
                }
            }
        }
        if(config!=null) {//设置null时，不去更新config
            instance.setConfig(config);
        }
        return instance;
    }

}
