#if defined(SCP03_TEST) && defined(DEBUG_LOW)

#include "sec_apdu.h"

#include "SCP03_transceive.h"
#include "SCP03.h"
#include "tz_debug.h"
#include "tz_log.h"


#define TYPE2_WITH_RESPONSE                 1
#define TYPE4_WITH_RESPONSE                 2
#define TYPE2_WITHOUT_RESPONSE              3

#define ERROR_TEST_UNKNOWN                  (-100)
#define ERROR_TEST_INVALID_PARAM_NULL       (-200)
#define ERROR_TEST_INVALID_PARAM_SL         (-300)
#define ERROR_TEST_INVALID_PARAM_TC         (-400)
#define ERROR_TEST_SELECT                   (-500)
#define ERROR_TEST_SCP_INIT                 (-600)
#define ERROR_TEST_SCP_OPERATION            (-700)
#define ERROR_TEST_SCP_NOT_9000             (-800)

void scp03_test(p_cmd_t cmd, p_rsp_t rsp){
    uint8_t ISD_AID[] = {0xA0, 0x00, 0x00, 0x01, 0x51, 0x00, 0x00, 0x00};
    uint8_t S3SSD[] = {0xA0, 0x00, 0x00, 0x01, 0x51, 0x53, 0x50, 0x41, 0x53, 0x33, 0x53, 0x53, 0x44};
    uint8_t Key_ENC[32] = {0,};
    uint8_t Key_MAC[32] = {0,};
    uint8_t Key_DEK[32] = {0,};
    
    uint8_t RPDU_DATA[256] = {0,};
    uint8_t payload1[255] = {0,};
    uint8_t payload2[255] = {0x4f, 0,};
    uint8_t payload3[255] = {0xFE, 0x14, 0xB0, 0x01, 0x00, 0xB2, 0x0F, 0xB1, 0x01, 0x02, 0x4F, 0x0A,
                        0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9,};
    rsp->ret = ERROR_TEST_UNKNOWN;
    uint8_t channelId = 0x00;
    secEse_7816_cpdu_t command1, command2, command3;
    command1.cla = 0x80;
    command1.ins = 0xca;
    command1.p1 = 0x9f;
    command1.p2 = 0x7f;
    command1.lc = 0;
    command1.cpdu_type = 0;
    command1.pdata = payload1;
    command1.le_type = 1;
    command1.le = 0;

    command2.cla = 0x80;
    command2.ins = 0xf2;
    command2.p1 = 0x80;
    command2.p2 = 0x00;
    command2.lc = 2;
    command2.cpdu_type = 0;
    command2.pdata = payload2;
    command2.le_type = 1;
    command2.le = 0;

    memcpy(payload3, S3SSD, sizeof(S3SSD));
    command3.cla = 0x80;
    command3.ins = 0xe2;
    command3.p1 = 0x90;
    command3.p2 = 0x00;
    command3.lc = 0x16;
    command3.cpdu_type = 0;
    command3.pdata = payload3;
    command3.le_type = 1;
    command3.le = 0;

    secEse_7816_cpdu_t commands[3] = {
        command1, command2, command3
    };
    secEse_7816_rpdu_t rpdu = {
        0, 0, RPDU_DATA, sizeof(RPDU_DATA)
    };

    SCPSTATUS scpStatus = SCP_FAIL;
    ESESTATUS isoStatus = ESESTATUS_FAILED;

    if (cmd == NULL || rsp == NULL || cmd-> data == NULL) {
        LOGE("invalid param null");
        rsp->ret = ERROR_TEST_INVALID_PARAM_NULL;
        return;
    }
    uint8_t sl = cmd->data[0];
    uint8_t tc = cmd->data[1];
    if (sl != 0x01 && sl != 0x03 && sl != 0x11 && sl != 0x33) {
        LOGE("invalid param sl");
        rsp->ret = ERROR_TEST_INVALID_PARAM_SL;
        return;
    }
    if (tc < 1 || tc > 3) {
        LOGE("invalid param tc");
        rsp->ret = ERROR_TEST_INVALID_PARAM_TC;
        return;
    }

    memcpy(Key_ENC, cmd->data + 2, 32);
    memcpy(Key_MAC, cmd->data + 2 + 32, 32);
    memcpy(Key_DEK, cmd->data + 2 + 32 + 32, 32);

    hex_print_tag_debug("ENC", Key_ENC, 32);
    hex_print_tag_debug("MAC", Key_MAC, 32);
    hex_print_tag_debug("DEK", Key_DEK, 32);


    LOGD("scp03_test SL: %02X, TC:%02X\n", sl, tc);
    secEseOpen(&channelId);
    isoStatus = secEseSelect(channelId, ISD_AID, 0, sizeof(ISD_AID), &rpdu);
    if (isoStatus != ESESTATUS_OK || rpdu.sw1 != 0x90 || rpdu.sw2 !=0x00) {
        LOGE("Failed to [SELECT]");
        rsp->ret = ERROR_TEST_SELECT;
        goto error;
    }
    rpdu.sw1 = 0;
    rpdu.sw2 = 0;
    rpdu.pdata = RPDU_DATA;
    rpdu.len = sizeof(RPDU_DATA);
    scpStatus = openSession(channelId, 0x32, Key_ENC, Key_MAC, Key_DEK, ISD_AID, sizeof(ISD_AID), sl);
    if (scpStatus != SCP_SUCCESS) {
        LOGE("Failed establish SCP03: 0x%08x", scpStatus);
        rsp->ret = ERROR_TEST_SCP_INIT;
        goto error;
    }
    scpStatus = apduTransceive(channelId, &commands[tc-1], &rpdu);
    if (scpStatus != SCP_SUCCESS) {
        LOGE("Failed establish SCP03: 0x%08x", scpStatus);
        rsp->ret = ERROR_TEST_SCP_OPERATION;
    } else {
        if(rpdu.sw1 != 0x90 || rpdu.sw2 !=0x00) {
            LOGE("Failed SW");
            goto error;
        }
        rsp->ret = scpStatus;
    }
    memcpy(rsp->data, rpdu.pdata, rpdu.len);
    rsp->dataLen = rpdu.len;
error:
    secEseClose(channelId);
}
#endif
