#include "process_cmd.h"
#include "tz_dk_cmds.h"
#include "tz_dk_errors.h"
#include "shared/Initialize_tl.h"
#include "shared/Finalize_tl.h"
// #include "shared/Open_Secure_Channel.h"
// #include "shared/Send_APDU.h"
// #include "shared/Close_Secure_Channel.h"
#include "dk_attn.h"
#include "dk_scp_common.h"
#include "SCP03lib.h"

#ifdef DK_DEBUG
#include "dk_test.h"
#endif

uint32_t process_cmd(
	tl_dk_ctx_t * ctx,
	uint32_t commandId,
	tciMessage_t * sendmsg,
	tciMessage_t * respmsg
)
{
	uint32_t ret;
	uint8_t flag;
	TTY_LOG("process_cmd for commandid : %x", commandId);

#ifdef DK_DEBUG
	ret = DK_SUCCESS;
#else
	ret = dk_ICCC_check();
#endif

	if(ret == DK_ERROR_INTEGRITY_FAILED) {
		return ret;
	}

	/* Process command message */
  if (CMD_TZ_DK_Open_Secure_Channel < commandId &&
      CMD_TZ_DK_Close_Secure_Channel > commandId) {

    ret = process_scp03_open_session(ctx, sendmsg->payload.scp03_transceive.payload.cmd, &respmsg->payload.scp03_open_session);
    if (!ret) {
        switch (commandId) {
        case CMD_TZ_DK_Create_CA:
            ret = process_scp03_create_ca(ctx, &sendmsg->payload.scp03_create_ca, &respmsg->payload.scp03_create_ca);
            respmsg->dkheader.header.len = sizeof(tz_scp03_create_ca_resp_t);
            break;
        case CMD_TZ_DK_Invoke_Read:
            ret = process_scp03_invoke_read(ctx, &sendmsg->payload.scp03_invoke_read, &respmsg->payload.scp03_invoke_read);
            respmsg->dkheader.header.len = sizeof(tz_scp03_invoke_read_resp_t);
            break;
        case CMD_TZ_DK_Write_Invoke_Read:
            ret = process_scp03_write_invoke_read(ctx, &sendmsg->payload.scp03_write_invoke_read, &respmsg->payload.scp03_write_invoke_read);
            respmsg->dkheader.header.len = sizeof(tz_scp03_write_invoke_read_resp_t);
            break;
        case CMD_TZ_DK_Write_Invoke:
            ret = process_scp03_write_invoke(ctx, &sendmsg->payload.scp03_write_invoke, &respmsg->payload.scp03_write_invoke);
            respmsg->dkheader.header.len = sizeof(tz_scp03_write_invoke_resp_t);
            break;
        case CMD_TZ_DK_Send_APDU:
            ret = process_apdu_transceive(ctx, &sendmsg->payload.scp03_transceive, &respmsg->payload.scp03_transceive);
            respmsg->dkheader.header.len = sizeof(tz_scp03_transceive_resp_t);
            break;
        case CMD_TZ_DK_SET_PRIVATE_DATA:
            ret = process_scp03_set_private_data(ctx, &sendmsg->payload.scp03_set_private_data, &respmsg->payload.scp03_set_private_data);
            respmsg->dkheader.header.len = sizeof(tz_scp03_set_private_data_resp_t);
            break;
        case CMD_TZ_DK_GET_PRIVATE_DATA:
            ret = process_scp03_get_private_data(ctx, &sendmsg->payload.scp03_get_private_data, &respmsg->payload.scp03_get_private_data);
            respmsg->dkheader.header.len = sizeof(tz_scp03_get_private_data_resp_t);
            break;
        default :
            DK_LOG_ERR("Command unknown");
            ret = DK_ERROR_NOT_SUPPORTED;
            break;
        }
    }
    ret = process_scp03_close_session(ctx);
  } else if (CMD_TZ_DK_Open_Non_Secure_Channel < commandId &&
             CMD_TZ_DK_Send_In_Session >= commandId) {

	TTY_LOG("Digitalkey : enter non scp03 block");

    switch (commandId) {
    case CMD_TZ_DK_Open_Select:
        ret = process_non_scp03_open_session(ctx, &respmsg->payload.scp03_open_session);
        respmsg->dkheader.header.len = sizeof(tz_scp03_transceive_resp_t);
        break;
    case CMD_TZ_DK_Send_In_Session:
        ctx->channel.is_open = 1;
        ctx->channel.id = sendmsg->payload.scp03_transceive.payload.cmd.channel_id;
        ret = process_apdu_transceive(ctx, &sendmsg->payload.scp03_transceive, &respmsg->payload.scp03_transceive);
        respmsg->dkheader.header.len = sizeof(tz_scp03_transceive_resp_t);
        break;
    case CMD_TZ_DK_Close:
        ctx->channel.is_open = 1;
        ctx->channel.id = sendmsg->payload.close_secure_channel.payload.cmd.channel_id;
        ret = process_non_scp03_close_session(ctx, &respmsg->payload.scp03_close_session);
        respmsg->dkheader.header.len = sizeof(tz_scp03_transceive_resp_t);
        break;
    case CMD_TZ_DK_Non_Scp_Send_APDU:
        ret = process_non_scp03_open_session(ctx, &respmsg->payload.scp03_open_session);
        ret = process_apdu_transceive(ctx, &sendmsg->payload.scp03_transceive, &respmsg->payload.scp03_transceive);
        respmsg->dkheader.header.len = sizeof(tz_scp03_transceive_resp_t);
        ret = process_non_scp03_close_session(ctx, &respmsg->payload.scp03_close_session);
			break;

		default :
            DK_LOG_ERR("Command unknown");
            ret = DK_ERROR_NOT_SUPPORTED;
            break;
	}
  } else {
	  switch (commandId) {
		case CMD_TZ_DK_Initialize:
			TTY_LOG("TZ_DIGITALKEY: process_cmd: CMD_TZ_DIGITALKEY_Initialize:");
			// ret = process_Initialize(ctx, &sendmsg->payload.init, &respmsg->payload.init);
			break;

		case CMD_TZ_DK_Open_Secure_Channel:
			TTY_LOG("open secure channel ");
			// ret = process_open_secure_channel(ctx, &sendmsg->payload.open_secure_channel, &respmsg->payload.open_secure_channel);
        //ret = process_scp03_open_session(ctx, &sendmsg->payload.scp03_open_session, &respmsg->payload.scp03_open_session);
			break;

		case CMD_TZ_DK_Close_Secure_Channel:
			TTY_LOG("close secure channel");
			// ret = process_close_secure_channel(ctx, &sendmsg->payload.close_secure_channel, &respmsg->payload.close_secure_channel);
			ret = process_scp03_close_session(ctx);
			break;

		case CMD_TZ_DK_Scp_Credential_Re_Wrap:
      TTY_LOG("scp03 crendential re wrap %d ", sendmsg->payload.scp03_setup_keys.payload.cmd.key_blob_size);
			ret = process_scp03_re_wrap(ctx, &sendmsg->payload.scp03_setup_keys, &respmsg->payload.scp03_setup_keys);
      respmsg->dkheader.header.len = sizeof(tz_scp03_setup_keys_resp_t);
			break;
			
		case CMD_TZ_DK_Finalize:
			TTY_LOG("TZ_DIGITALKEY: process_cmd: CMD_TZ_DIGITALKEY_Finalize:");
			// ret = process_Finalize(ctx, &sendmsg->payload.finalize, &respmsg->payload.finalize);
			break;

		case CMD_TZ_DK_Test:
			TTY_LOG("TZ_DIGITALKEY: process_cmd: CMD_TZ_DK_Test:");
			ret = DK_SUCCESS;
			break;
#ifdef DK_DEBUG
		case CMD_TZ_DK_run_tests:
			TTY_LOG("running tests");
			ret = run_all_tests();
			break;
#endif
		default:
			// TODO: return UNKNOW_COMMAND error
			TTY_LOG("Command unknown");
			ret = DK_ERROR_NOT_SUPPORTED;
	}
  }
  
	TTY_LOG("end ret %d", ret);

	return ret;
}
