#include "command.h"

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>

#include <tees_log.h>
#include <tee_client_api.h>

#if defined(QSEE)
const TEEC_UUID kFtestClientTaUuid = {0x70615f66, 0x7465, 0x7374, {
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}};
#elif defined(TBASE)
const TEEC_UUID kFtestClientTaUuid = {0xffffffff, 0x0000, 0x0000, {
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79}};
#elif defined(TEEGRIS)
const TEEC_UUID kFtestClientTaUuid = {0x00000000, 0x0000, 0x0000, {
    0x00, 0x00, 0x54, 0x50, 0x52, 0x4f, 0x43, 0x41}};
#endif

static char buffer[32];

int main(int argc, char **argv) {
  MB_LOGD("Starting canary client...\n");
  int result = EXIT_FAILURE;

  TEEC_Context context = {0};
  TEEC_Session session = {0};

  do {
    uint32_t return_origin;
    TEEC_Operation operation = {0};
    PaHandler handler = {0};
    TciCommand tci_command = {0};

    MB_LOGD("Running TEEC_InitializeContext...\n");
    TEEC_Result status = TEEC_InitializeContext(NULL, &context);
    if (status != TEEC_SUCCESS) {
      break;
    }

    MB_LOGD("Running TEEC_OpenSession...\n");
    status = TEEC_OpenSession(&context, &session, &kFtestClientTaUuid, 0, NULL,
                              NULL, &return_origin);
    if (status != TEEC_SUCCESS) {
      break;
    }

    MB_LOGD("Running PaHandlerCreate...\n");
    if (PaHandlerCreate(&handler) != PA_SUCCESS) {
      break;
    }

    if (argc >= 2) {
      tci_command.address = (uint64_t) buffer;
      tci_command.size = sizeof(buffer);

      if (0 == strcmp(argv[1], "read")) {
        MB_LOGD("Read...\n");
        tci_command.cmdId = kCommandReadFromNwdTask;
      } else if (0 == strcmp(argv[1], "write")) {
        MB_LOGD("Write...\n");
        tci_command.cmdId = kCommandWriteToNwdTask;
      } else {
        MB_LOGD("Authenticate app by name [%s]...\n", argv[1]);
        tci_command.cmdId = kAuthenticateByAppName;
        strncpy(tci_command.app_name, argv[1], sizeof(tci_command.app_name));
      }
    } else {
      MB_LOGD("Authentication...\n");
      tci_command.cmdId = kTestSimpleAuthenticate;
    }

    tci_command.handler = handler;

    operation.paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_TEMP_INOUT, TEEC_NONE,
                                            TEEC_NONE, TEEC_NONE);
    operation.params[0].tmpref.buffer = &tci_command;
    operation.params[0].tmpref.size = sizeof(tci_command);

    MB_LOGD("Running TEEC_InvokeCommand...\n");
    status = TEEC_InvokeCommand(&session, tci_command.cmdId, &operation,
                                &return_origin);

    PaHandlerDestroy(&handler);

    if (status == TEEC_SUCCESS && tci_command.tz_result == PA_TZ_PROCA_NOT_SUPPORTED) {
      MB_LOGD("Canary client ends with not supported!\n");
      printf("NOT SUPPORTED\n");
      break;
    }

    if (status != TEEC_SUCCESS || tci_command.tz_result != PA_TZ_SUCCESS) {
      MB_LOGD("Canary client ends with FAIL!\n");
      printf("FAILED : 0x%x\n", tci_command.tz_result);
      break;
    }

    MB_LOGD("Canary client ends with SUCCESS!\n");
    printf("SUCCESS\n");

    // Finally to set successfully result
    result = EXIT_SUCCESS;
  } while (0);

  TEEC_CloseSession(&session);
  TEEC_FinalizeContext(&context);

  return result;
}
