package h.com.serialportapi.comn;

import android.os.SystemClock;
import android.util.Log;

import com.licheedev.myutils.LogPlus;

import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;

import h.com.serialportapi.comn.message.DESFire;
import h.com.serialportapi.comn.message.ICMessage;
import h.com.serialportapi.comn.message.LogManager;
import h.com.serialportapi.comn.message.RecvMessage;
import h.com.serialportapi.util.ByteUtil;

/**
 * 读串口线程
 */
public class SerialReadThread extends Thread {

    private static final String TAG = "SerialReadThread";

    private BufferedInputStream mInputStream;

    public SerialReadThread(InputStream is) {
        mInputStream = new BufferedInputStream(is);
    }

    private ReaderListener listener;
    private ActivityListener activityListener;
    private DesFireListener desFireLisnter;

    private static String cmds;

    public static void setCmd(String cmd) {
        cmds = cmd;
    }

    public void setActivityListener(ActivityListener activityListener) {
        listener = null;
        desFireLisnter = null;
        this.activityListener = activityListener;
    }

    public void setListener(ReaderListener listener) {
        activityListener = null;
        desFireLisnter = null;
        this.listener = listener;
    }

    public void setDesFireLisnter(DesFireListener lisnter) {
        lisnter = null;
        activityListener = null;
        desFireLisnter = lisnter;
    }

    @Override
    public void run() {
        byte[] received = new byte[1024];
        int size;

        LogPlus.e("开始读线程");

        while (true) {

            if (Thread.currentThread().isInterrupted()) {
                break;
            }
            try {

                int available = mInputStream.available();

                if (available > 0) {
                    size = mInputStream.read(received);
                    if (size > 0) {
                        onDataReceive(received, size, 0);
                    }
                } else {
                    // 暂停一点时间，免得一直循环造成CPU占用率过高
                    SystemClock.sleep(1);
                }
            } catch (IOException e) {
                LogPlus.e("读取数据失败", e);
            }
            //Thread.yield();
        }

        LogPlus.e("结束读进程");
    }

    /**
     * 处理获取到的数据
     *
     * @param received
     * @param size
     */

    private static String receiveString = "";
    private static int receiveNum;

    private void onDataReceive(byte[] received, int size) {
        // TODO: 2018/10/22 解决粘包、分包等
        String hexStr = ByteUtil.bytes2HexStr(received, 0, size);
        Log.i("onDataReceive", hexStr);
        if (isConfirm(hexStr)) {
            LogManager.instance().post_r(new RecvMessage(hexStr));//这个方法去更新listview
            // TODO:当线程读到了串口返回的东西会回调该方法
            if (listener != null) {
                listener.transmitData(hexStr);
            } else if (activityListener != null) {
                if (hexStr.length() >= 26) {
                    ICMessage message = new ICMessage();
                    message.setTag_Type(hexStr.substring(8, 11));
                    message.setSAK(hexStr.substring(12, 15));
                    message.setUID_number(hexStr.substring(16, hexStr.length() - 2));
                    activityListener.piccActivity(message);
                } else {
                    ICMessage message = new ICMessage();
                    message.setTag_Type("-");
                    message.setSAK("-");
                    message.setUID_number("-");
                    activityListener.piccActivity(message);
                }
            } else if (desFireLisnter != null) {
                DESFire desFire = new DESFire();
                desFire.setAidno(hexStr.substring(8, 10));
                ArrayList<String> arrayList = new ArrayList<>();
                for (int i = 0; i < Integer.valueOf(desFire.getAidno()); i++) {
                    arrayList.add(hexStr.substring(10 + i * 6, 16 + i * 6));
                }
                desFire.setAids(arrayList);
            }
        } else {
            receiveString = receiveString + hexStr;
            receiveNum = receiveNum + 1;
            if (isConfirm(receiveString)) {
                LogManager.instance().post_r(new RecvMessage(hexStr));//这个方法去更新listview
                // TODO:当线程读到了串口返回的东西会回调该方法
                if (listener != null) {
                    listener.transmitData(receiveString);
                } else if (activityListener != null) {
                    if (hexStr.length() >= 26) {
                        ICMessage message = new ICMessage();
                        message.setTag_Type(hexStr.substring(8, 11));
                        message.setSAK(hexStr.substring(12, 15));
                        message.setUID_number(hexStr.substring(16, hexStr.length() - 2));
                        activityListener.piccActivity(message);
                    } else {
                        ICMessage message = new ICMessage();
                        message.setTag_Type("-");
                        message.setSAK("-");
                        message.setUID_number("-");
                        activityListener.piccActivity(message);
                    }
                }
                if (desFireLisnter != null) {

                }
                receiveString = "";
                receiveNum = 0;
            } else if (receiveNum == 2) {
                receiveNum = 0;
                receiveString = "";
            }
        }
    }

    public void onDataReceive(byte[] received, int size, int cmd) {
        // TODO: 2018/10/22 解决粘包、分包等
        String hexStr = ByteUtil.bytes2HexStr(received, 0, size);
        Log.i("onDataReceive", hexStr);

        if (hexStr.substring(0, 2).equals("50") | hexStr.substring(0, 2).equals("F0")) {
            receiveString = "";
        }
        if (isConfirm(hexStr) && hexStr.substring(6, 8).equals(cmds) && (hexStr.substring(0, 2).equals("50") | hexStr.substring(0, 2).equals("F0"))) {
            LogManager.instance().post_r(new RecvMessage(hexStr));//这个方法去更新listview
            // TODO:当线程读到了串口返回的东西会回调该方法
            if (listener != null) {
                listener.transmitData(hexStr);
            } else if (activityListener != null) {
                if (hexStr.length() >= 26) {
                    ICMessage message = new ICMessage();
                    message.setTag_Type(hexStr.substring(8, 12));
                    message.setSAK(hexStr.substring(12, 14));
                    message.setUID_number(hexStr.substring(16, hexStr.length() - 2));
                    activityListener.piccActivity(message);
                } else {
                    ICMessage message = new ICMessage();
                    message.setTag_Type("-");
                    message.setSAK("-");
                    message.setUID_number("-");
                    activityListener.piccActivity(message);
                }
            }else if (desFireLisnter != null) {
                DESFire desFire = new DESFire();
                desFire.setAidno(hexStr.substring(8, 10));
                ArrayList<String> arrayList = new ArrayList<>();
                for (int i = 0; i < Integer.valueOf(desFire.getAidno()); i++) {
                    arrayList.add(hexStr.substring(10 + i * 6, 16 + i * 6));
                }
                desFire.setAids(arrayList);
                desFireLisnter.DesFireCard(desFire);
            }
        } else {
            receiveString = receiveString + hexStr;
            if (isConfirm(receiveString) && receiveString.substring(6, 8).equals(cmds) && (receiveString.substring(0, 2).equals("50") | receiveString.substring(0, 2).equals("F0"))) {
                LogManager.instance().post_r(new RecvMessage(receiveString));//这个方法去更新listview
                // TODO:当线程读到了串口返回的东西会回调该方法
                if (listener != null) {
                    listener.transmitData(receiveString);
                } else if (activityListener != null) {
                    ICMessage message = new ICMessage();
                    if (receiveString.length() >= 26) {
                        message.setTag_Type(receiveString.substring(8, 12));
                        message.setSAK(receiveString.substring(12, 14));
                        message.setUID_number(receiveString.substring(16, receiveString.length() - 2));
                        activityListener.piccActivity(message);
                    } else {
                        message.setTag_Type("-");
                        message.setSAK("-");
                        message.setUID_number("-");
                        activityListener.piccActivity(message);
                    }
                }else if (desFireLisnter != null) {
                    DESFire desFire = new DESFire();
                    desFire.setAidno(hexStr.substring(8, 10));
                    ArrayList<String> arrayList = new ArrayList<>();
                    for (int i = 0; i < Integer.valueOf(desFire.getAidno()); i++) {
                        arrayList.add(hexStr.substring(10 + i * 6, 16 + i * 6));
                    }
                    desFire.setAids(arrayList);
                    desFireLisnter.DesFireCard(desFire);
                }
            }
        }
    }

    /**
     * receive data verification
     */
    public void dataVerification(String receiveData) {
        if (receiveData.substring(0, 2).equals("50")) {
            if (isConfirm(receiveData)) {
                LogManager.instance().post_r(new RecvMessage(receiveData));//这个方法去更新listview
                // TODO:当线程读到了串口返回的东西会回调该方法
                if (listener != null) {
                    listener.transmitData(receiveData);
                } else if (activityListener != null) {
                    if (receiveData.length() >= 26) {
                        ICMessage message = new ICMessage();
                        message.setTag_Type(receiveData.substring(8, 11));
                        message.setSAK(receiveData.substring(12, 15));
                        message.setUID_number(receiveData.substring(16, receiveData.length() - 2));
                        activityListener.piccActivity(message);
                    } else {
                        ICMessage message = new ICMessage();
                        message.setTag_Type("-");
                        message.setSAK("-");
                        message.setUID_number("-");
                        activityListener.piccActivity(message);
                    }
                }
            } else {

            }
        } else if (receiveData.substring(0, 2).equals("F0")) {
            if (isConfirm(receiveData)) {

            } else {

            }
        }
    }

    public static boolean isConfirm(String comm) {
        return comm.substring(comm.length() - 2, comm.length()).equals(setXor(comm.substring(0, comm.length() - 2)));
    }

    private static String setXor(String requestComm) {
        ArrayList<String> buff = new ArrayList<>();
        for (int i = 0; i < requestComm.length(); i = i + 2) {
            buff.add(requestComm.substring(i, i + 2));
        }
        int r = 0;
        for (String b : buff) {
            //把16进制的转换为10进制的数进行异或操作
            r = r ^ Integer.parseInt(String.valueOf(b), 16);
        }
        //得到异或的数之后在转换成16进制的
        String hex = Integer.toHexString(r & 0xFF);
        if (hex.length() == 1) {
            hex = "0" + hex;
        }
        return hex.toUpperCase();
    }

    private void postMessage(String hexStr) {
        LogManager.instance().post_r(new RecvMessage(hexStr));//这个方法去更新listview
        // TODO:当线程读到了串口返回的东西会回调该方法
        if (listener != null) {
            listener.transmitData(hexStr);
        } else if (activityListener != null) {
            if (hexStr.length() >= 26) {
                ICMessage message = new ICMessage();
                message.setTag_Type(hexStr.substring(8, 11));
                message.setSAK(hexStr.substring(12, 15));
                message.setUID_number(hexStr.substring(16, hexStr.length() - 2));
                activityListener.piccActivity(message);
            } else {
                ICMessage message = new ICMessage();
                message.setTag_Type("-");
                message.setSAK("-");
                message.setUID_number("-");
                activityListener.piccActivity(message);
            }
        }
    }

    /**
     * 停止读线程
     */
    public void close() {

        try {
            mInputStream.close();
        } catch (IOException e) {
            LogPlus.e("异常", e);
        } finally {
            super.interrupt();
        }
    }

    public interface ReaderListener {
        void transmitData(String msg);
    }

    public interface ActivityListener {
        void piccActivity(ICMessage message);
    }

    public interface DesFireListener {
        void DesFireCard(DESFire desFire);
    }
}
