#include <comdef.h>
#include <string.h>
#include <locale.h>

#include "mz_config.h"
#include "mz_log.h"
#include "tl_tlcApi.h"
#include "tl_handler.h"
#include "mz_types.h"
#include "version_info.h"

// Note, following defines are for 8x26 chipset (for those not using *.ld files)
#define TRUSTLET_MAIN_STACK_SIZE    64  * 1024
#define TRUSTLET_HEAP_SIZE          128 * 1024

// QSEE TZ App name
char TZ_APP_NAME[] = { "mz" };

// Termination Code
#define EXIT_ERROR ((uint32_t)(-1))

// Local buffer to copy shared memory,
// all crypto operation should use only internal buffers
static tciMessage_t msg_buffer;

void tz_app_init(void)
{
    // print vesrion info
    print_version_info(MODULE_IDENTITY_TA);

    // print trustlet name and version
    MZ_LOG(err_level_info, LOG_TAG, "================================================");
    MZ_LOG(err_level_info, LOG_TAG, "  MZ trustlet version: " VERSION_NUMBER);
    MZ_LOG(err_level_info, LOG_TAG, "  heap : %d, stack : %d ", TRUSTLET_HEAP_SIZE,
            TRUSTLET_MAIN_STACK_SIZE);
    MZ_LOG(err_level_info, LOG_TAG, "================================================");

}

/**
   @brief
   Data structure

   @param[in]   cmd_id      Requested command
   @param[in]   data        information (could be data or a pointer to the memory that holds the data
   @param[in]   len         if data is ptr to some buffer, len indicates length of the buffer
   @param[in]   test_buf_size  When running crypto test, this indicates the test packet size
 */

void tz_app_cmd_handler(void *cmd, uint32 cmdlen, void *rsp, uint32 rsplen)
{
    MZ_LOG_EN(LOG_TAG, "%s: Called\n", "ta.qc");
    if ((NULL == cmd) || (NULL == rsp) || !cmdlen || !rsplen)
    {
        MZ_LOG_E(LOG_TAG, MZ_RET_E_ASSERT,
                  "invalid cmd (got %p, %d, need %d), rsp=%p, rsplen=%d, exit", cmd, cmdlen, 4,
                  rsp, rsplen);
        return;
    }

    MZ_LOG(err_level_debug, LOG_TAG, "[%s] Got cmd = %p, cmdlen = %d, rsp=%p, rsplen=%d, exit",
            __func__, cmd, cmdlen, rsp, rsplen);

    memset(&msg_buffer, 0, sizeof(msg_buffer));

    if (sizeof(msg_buffer) >= cmdlen)
    {
        memcpy(&msg_buffer, cmd, cmdlen);
    }
    else
    {
        MZ_LOG_E(LOG_TAG, MZ_RET_E_OVERFLOW, "[%s] Too big command length\n", __func__);
        msg_buffer.response.status = MZ_RET_E_OVERFLOW;
        goto end;
    }

    msg_buffer.response.status = TZ_COMMAND((void *)msg_buffer.msgData.buffer);

    MZ_LOG(err_level_info, LOG_TAG, "[%s] Return code %u \n", __func__,
            msg_buffer.response.header.returnCode);
end:
    if (sizeof(msg_buffer) <= rsplen)
    {
        memcpy(rsp, &msg_buffer, sizeof(msg_buffer));
    }
    else
    {
        MZ_LOG_E(LOG_TAG, MZ_RET_E_LENGTH, "[%s] Too SMALL response length. Can't put TCI\n",
                  __func__);
    }
    MZ_LOG_EN(LOG_TAG, "%s: End\n", "ta.qc");
}

// QSEE TZ App Shutdown
void tz_app_shutdown(void)
{
    // app specific shutdown code
    MZ_LOG_EN(LOG_TAG, "[%s] Destroy\n", "ta.qc");
}
