package com.unibuy.smartdevice.devices;

import android.content.Context;
import android.util.Log;

import androidx.core.view.InputDeviceCompat;

import com.unibuy.smartdevice.R;
import com.unibuy.smartdevice.exception.Logs;
import com.unibuy.smartdevice.exception.LogsParseException;

import java.nio.charset.StandardCharsets;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.Locale;

public class DevNFCPay {
    private Logs logs;
    private final byte ACK = 6;
    private final byte ETX = 3;
    private final byte NAK = 21;
    private final byte STX = 2;

    private String type = "NCCC";
    private String swipeString = "";
    private String dataLength = "";
    private boolean isScaning = false;
    private static Context context;

    public DevNFCPay(Context context) {
        this.logs = new Logs(this.getClass());
        this.context = context.getApplicationContext();
    }

    //    public DevNFCPay() {
//        String[] SerialConfig = "/dev/ttymxc2,9600".split(",");
//        String pathName = SerialConfig[0];
//        int baudrate = Integer.parseInt(SerialConfig[1]);
//        if (SerialConfig.length > 2) {
//            dataLength = SerialConfig[2];
//            type = "TSIB";
//        } else {
//            type = "NCCC";
//        }
//    }

    public byte[] checkout() { //NCCC信用卡結帳
        String date = new SimpleDateFormat("yyMMddHHmmss", Locale.US).format(new Date());
        String str = "I       50                                            " + date + "                                                                                                                                                                                                                                                                                                                                              ";
        byte[] data = new byte[403];
        data[0] = STX;
        System.arraycopy(str.getBytes(), 0, data, 1, str.length());
        data[401] = ETX;
        for (int i = 1; i < 402; i++) {
            data[402] = (byte) (data[402] ^ data[i]);
        }
        return data;
    }

    public byte[] reconcile() { //TSIB特約商店結帳
        String date = new SimpleDateFormat("yyMMddHHmmss", Locale.US).format(new Date());
        String strDefault = dataLength.isEmpty() ? "      " : "220001";
        String str = dataLength + "I" + strDefault + " 50                                            " + date + "                                                                                                                                                                                                                                                                                                                                              ";
        int l = str.length();
        byte[] data = new byte[l + 3];
        data[0] = STX;
        int l2 = l + 1;
        System.arraycopy(str.getBytes(), 0, data, 1, l);
        int l3 = l2 + 1;
        data[l2] = ETX;
        for (int i = 1; i < l3; i++) {
            data[l3] = (byte) (data[l3] ^ data[i]);
        }
        swipeString = new String(data, StandardCharsets.UTF_8).substring(dataLength.length());
        return data;
    }

    public byte[] reset() { //重啟
        byte[] data = new byte[403];
        data[0] = STX;
        System.arraycopy("I       99".getBytes(), 0, data, 1, "I       99".length());
        data[401] = ETX;
        for (int i = 1; i < 402; i++) {
            data[402] = (byte) (data[402] ^ data[i]);
        }
        return data;
    }

    /*
    170000483***86   00000202206JS2  00900248                                                                                                                                                   cI0702 01300084*69  000201J2000115                                               i
    \u0006
    192130096******11  000000248 0000794    1846                                              200014  M                   A\/MdC+4PLjtONdrF=                                   M
    \u0006
    1N 56222231        030047
    \u0006
    \u0006
    9006*7  0000242325064   0015700                               020014        3x9iC+4uPL6jtO+eNbUAredrVfpnFL4=       T01
    \u0003
    */

    private HashMap<String, String> decode(String s) {
        s.substring(1, 2);
        s.substring(2, 8);
        s.substring(9, 11);
        s.substring(11, 12);
        s.substring(12, 14);
        s.substring(15, 20);
        s.substring(20, 39);
        s.substring(39, 43);
        s.substring(43, 55);
        s.substring(55, 61);
        s.substring(61, 67);
        s.substring(67, 76);
        s.substring(76, 77);
        String C15_ResponseCode = s.substring(77, 81);
        s.substring(81, 96);
        s.substring(96, 104);
        s.substring(116, 134);
        s.substring(134, 135);
        s.substring(175, 177);
        s.substring(177, 189);
        s.substring(189, 201);
        s.substring(201, 213);
        s.substring(213, 215);
        s.substring(215, 221);
        s.substring(223, 224);
        s.substring(224, 232);
        s.substring(232, 240);
        s.substring(240, 252);
        s.substring(InputDeviceCompat.SOURCE_KEYBOARD, 307);
        s.substring(307, 313);
        s.substring(313, 314);
        s.substring(314, 315);
        s.substring(315, 318);

        String responseCode = C15_ResponseCode;
        String status = String.valueOf(s.charAt(1));
        String category = swipeString.length()>0? swipeString.substring(1): "";
        String message = s.substring(1);

        logs.info("responseCode:" + responseCode);
        logs.info("status:" + status);
        logs.info("category:" + category);
        logs.info("message:" + message);

        HashMap<String, String> responseMap = new HashMap<>();
        responseMap.put("code", responseCode);
        responseMap.put("status", status);
        responseMap.put("category", category);
        responseMap.put("message", message);

        return responseMap;
    }

    public HashMap<String, String> read(String rxData) throws LogsParseException {
        int stx = rxData.lastIndexOf(String.format("%c", Byte.valueOf(STX)));
        int etx = rxData.indexOf(String.format("%c", Byte.valueOf(ETX)));
        while (stx > etx) {
            stx = rxData.lastIndexOf(String.format("%c", Byte.valueOf(STX)), stx - 1);
        }
        if (stx >= 0) {
            return decode(rxData.substring(dataLength.length() + stx, etx));
        } else {
            throw new LogsParseException(logs, "Decode parsing failed");
        }
    }

    //check = 3
    public byte[] ok() {
        return new byte[]{ACK, ACK};
    }
    public byte[] settlement(int type) {
        byte[] data = new byte[401];
        Arrays.fill(data, (byte) 32);
        data[1] = 73;
        System.arraycopy("2200".getBytes(), 0, data, 2, 4);
        System.arraycopy("01".getBytes(), 0, data, 6, 2);
        switch (type) { //TSIB特約商店結帳
            case 1:
                System.arraycopy("50".getBytes(), 0, data, 9, 2);
                break;
            case 251: //一卡通
                System.arraycopy("71".getBytes(), 0, data, 9, 2);
                System.arraycopy("51".getBytes(), 0, data, 12, 2);
                break;
            case 252: //悠遊卡
                System.arraycopy("71".getBytes(), 0, data, 9, 2);
                System.arraycopy("52".getBytes(), 0, data, 12, 2);
                break;
        }
        int l = dataLength.length();
        byte[] cmd = new byte[l + 403];
        System.arraycopy(dataLength.getBytes(), 0, cmd, 1, l);
        System.arraycopy(data, 1, cmd, l + 1, 400);
        int l2 = cmd.length - 1;
        cmd[0] = STX;
        cmd[l2 - 1] = ETX;
        for (int i = 1; i < l2; i++) {
            cmd[l2] = (byte) (cmd[l2] ^ cmd[i]);
        }
        swipeString = new String(cmd, StandardCharsets.UTF_8).substring(dataLength.length());
        return cmd;
    }

    public byte[] swipe(int payType, int price) {
        isScaning = true;
        if (!type.equals("TSIB")) {
            return swipeNCCC(payType == 2 ? 'E' : 'N', price);
        } else {
            return swipeTSIB(payType != 4 ? payType : 1, price);
        }
    }

    public byte[] swipeTSIB(int type, int price) {
        Date now = new Date();
        byte[] data = new byte[401];
        Arrays.fill(data, (byte) 32);
        data[1] = 73;
        System.arraycopy("2200".getBytes(), 0, data, 2, 4);
        System.arraycopy("01".getBytes(), 0, data, 6, 2);
        System.arraycopy(String.format(Locale.ROOT, "%012d", Integer.valueOf(price * 100)).getBytes(), 0, data, 43, 12);
        System.arraycopy(new SimpleDateFormat("yyMMddHHmmss", Locale.US).format(now).getBytes(), 0, data, 55, 12);

        switch (type) {
            case 1:
                System.arraycopy("01".getBytes(), 0, data, 9, 2);
                System.arraycopy(new SimpleDateFormat("yyMMddHHmmssSSSS", Locale.US).format(now).getBytes(), 0, data, 368, 16);
                break;
            case 251:
                System.arraycopy("71".getBytes(), 0, data, 9, 2);
                System.arraycopy("51".getBytes(), 0, data, 12, 2);
                break;
            case 252:
                System.arraycopy("71".getBytes(), 0, data, 9, 2);
                System.arraycopy("52".getBytes(), 0, data, 12, 2);
                break;
        }
        byte[] cmd = new byte[409];
        cmd[0] = STX;
        Log.i("swipteISIB", "length:" + dataLength.getBytes());
        System.arraycopy(dataLength.getBytes(), 0, cmd, 1, 6);
        System.arraycopy(data, 1, cmd, 7, 400);
        cmd[407] = ETX;
        for (int i = 1; i < 408; i++) {
            cmd[408] = (byte) (cmd[408] ^ cmd[i]);
        }
        swipeString = new String(cmd, StandardCharsets.UTF_8).substring(dataLength.length());
        return cmd;
    }

    private byte[] swipeNCCC(char type2, int price) {
        String format = String.format(
                Locale.ROOT,
                "I       01%c03                             %012d%s                                                 Nexsys1412        2                                                                                                                                                                                                                                                                          ",
                Character.valueOf(type2),
                Integer.valueOf(price * 100),
                new SimpleDateFormat("yyMMddHHmmss", Locale.US).format(new Date()));
        swipeString = format;
        format.substring(9, 11);
        swipeString.charAt(11);
        swipeString.substring(12, 14);
        swipeString.substring(43, 55);
        swipeString.substring(55, 61);
        swipeString.substring(61, 67);
        swipeString.substring(116, 134);
        swipeString.charAt(134);
        int l = swipeString.length();
        byte[] cmd = new byte[l + 3];
        System.arraycopy(swipeString.getBytes(), 0, cmd, 1, l);
        int l2 = cmd.length - 1;
        cmd[0] = STX;
        cmd[401] = ETX;
        for (int i = 1; i < l2; i++) {
            cmd[l2] = (byte) (cmd[l2] ^ cmd[i]);
        }
        return cmd;
    }
    /*
    沒有使用
    */
    public byte[] echo() {
        byte[] data = new byte[409];
        Arrays.fill(data, (byte) 32);
        data[408] = 0;
        System.arraycopy(dataLength.getBytes(), 0, data, 1, dataLength.length());
        data[7] = 73;
        data[8] = 50;
        data[9] = 50;
        data[10] = 48;
        data[11] = 48;
        data[12] = 48;
        data[13] = 49;
        data[15] = 57;
        data[16] = 57;
        data[0] = STX;
        data[407] = ETX;
        for (int i = 1; i < 408; i++) {
            data[408] = (byte) (data[408] ^ data[i]);
        }
        return data;
    }

    /*
    沒有使用
     */
    public byte[] abort(char type2, int price) {
        String format = String.format(
                Locale.ROOT,
                "I       30%c03                             %012d%s                                                 Nexsys1412        2                                                                                                                                                                                                                                                                          ",
                Character.valueOf(type2),
                Integer.valueOf(price * 100),
                new SimpleDateFormat("yyMMddHHmmss", Locale.US).format(new Date()));
        swipeString = format;
        format.substring(9, 11);
        swipeString.charAt(11);
        swipeString.substring(12, 14);
        swipeString.substring(14, 20);
        swipeString.substring(43, 55);
        swipeString.substring(55, 61);
        swipeString.substring(61, 67);
        swipeString.substring(116, 134);
        swipeString.charAt(134);
        int l = swipeString.length();
        byte[] cmd = new byte[l + 3];
        System.arraycopy(swipeString.getBytes(), 0, cmd, 1, l);
        int l2 = cmd.length - 1;
        cmd[0] = STX;
        cmd[401] = ETX;
        for (int i = 1; i < l2; i++) {
            cmd[l2] = (byte) (cmd[l2] ^ cmd[i]);
        }
        return cmd;
    }

    /*
    0000 ➔ 交易成功
    0001 ➔ 交易失敗
    0002 ➔ 請連絡銀行
    0003 ➔ 交易逾時
    0004 ➔ 操作錯誤
    0005 ➔ 通訊失敗
    0006 ➔ 使用者終止交易
    0009 ➔ 非參加機構卡片
    0010 ➔ 電文錯誤
    0011 ➔ 非聯名卡-客製化參數 075/103 使用
    0012 ➔ 電票金額超過上限
    0013 ➔ 票卡已鎖
    0014 ➔ 無法比對原始電票交易
    0015 ➔ 票卡未開啟自動加值
    0016 ➔ 電票餘額不足
    0017 ➔ 多張票卡讀取失敗
    0018 ➔ 請重新感應卡片
    1001 ➔ 信用卡及電票皆結帳失敗
    1002 ➔ 信用卡結帳成功，電票結帳失敗
    1003 ➔ 信用卡結帳失敗，電票結帳成功
     */

    public static String recordMessage(String code) {
        switch (code) {
            case "0000":
                return context.getString(R.string.successful_transaction);//交易成功

            case "0001":
                return context.getString(R.string.transaction_failure);//交易失敗

            case "0002":
                return context.getString(R.string.please_contact_your_bank);//請連絡銀行

            case "0003":
                return context.getString(R.string.transaction_timeout);//交易逾時

            case "0004":
                return context.getString(R.string.operational_error);//操作錯誤

            case "0005":
                return context.getString(R.string.communication_failure);//通訊失敗

            case "0006":
                return context.getString(R.string.user_terminates_transaction);//使用者終止交易

            case "0009":
                return context.getString(R.string.non_participating_institution_card);//非參加機構卡片

            case "0010":
                return context.getString(R.string.message_error);//電文錯誤

            case "0011":
                return context.getString(R.string.non_co_branded_card_customized_parameters_075_103_use);//非聯名卡-客製化參數 075/103 使用

            case "0012":
                return context.getString(R.string.amount_of_the_electronic_bill_exceeds_the_upper_limit);//電票金額超過上限

            case "0013":
                return context.getString(R.string.ticket_locked);//票卡已鎖

            case "0014":
                return context.getString(R.string.unable_compare_original_electronic_bill_transaction);//無法比對原始電票交易

            case "0015":
                return context.getString(R.string.ticket_card_has_not_enabled_automatic_recharge);//票卡未開啟自動加值

            case "0016":
                return context.getString(R.string.insufficient_balance_on_electronic_bill);//電票餘額不足

            case "0017":
                return context.getString(R.string.multiple_tickets_failed_to_read);//多張票卡讀取失敗

            case "0018":
                return context.getString(R.string.please_scan_card_again);//請重新感應卡片

            case "1001":
                return context.getString(R.string.credit_card_electronic_bill_payment_failed);//信用卡及電票皆結帳失敗

            case "1002":
                return context.getString(R.string.credit_card_payment_successful_electronic_bill_payment_failed);//信用卡結帳成功，電票結帳失敗

            case "1003":
                return context.getString(R.string.credit_card_payment_failed_electronic_bill_payment_succeeded);//信用卡結帳失敗，電票結帳成功

        }

        return context.getString(R.string.abnormal_response_message_error);//回應異常，電文錯誤
    }
//public static String recordMessage(String code) {
//    switch (code) {
//        case "0000":
//            return context.getString(R.string.successful_transaction);//交易成功
//
//        case "0001":
//            return "交易失敗";//交易失敗
//
//        case "0002":
//            return "請連絡銀行";//請連絡銀行
//
//        case "0003":
//            return "交易逾時";//交易逾時
//
//        case "0004":
//            return "操作錯誤";//操作錯誤
//
//        case "0005":
//            return "通訊失敗";//通訊失敗
//
//        case "0006":
//            return "使用者終止交易";//使用者終止交易
//
//        case "0009":
//            return "非參加機構卡片";//非參加機構卡片
//
//        case "0010":
//            return "電文錯誤";//電文錯誤
//
//        case "0011":
//            return "非聯名卡-客製化參數 075/103 使用";//非聯名卡-客製化參數 075/103 使用
//
//        case "0012":
//            return "電票金額超過上限";//電票金額超過上限
//
//        case "0013":
//            return "票卡已鎖";//票卡已鎖
//
//        case "0014":
//            return "無法比對原始電票交易";//無法比對原始電票交易
//
//        case "0015":
//            return "票卡未開啟自動加值";//票卡未開啟自動加值
//
//        case "0016":
//            return "電票餘額不足";//電票餘額不足
//
//        case "0017":
//            return "多張票卡讀取失敗";//多張票卡讀取失敗
//
//        case "0018":
//            return "請重新感應卡片";//請重新感應卡片
//
//        case "1001":
//            return "信用卡及電票皆結帳失敗";//信用卡及電票皆結帳失敗
//
//        case "1002":
//            return "信用卡結帳成功，電票結帳失敗";//信用卡結帳成功，電票結帳失敗
//
//        case "1003":
//            return "信用卡結帳失敗，電票結帳成功";//信用卡結帳失敗，電票結帳成功
//
//    }
//
//    return "回應異常，電文錯誤";//回應異常，電文錯誤
//}

}
