#include <tee_internal_api.h>
#include <protocol.h>
#include <socket_utils.h>
#include <tees_log.h>
#include <time.h>
#include <stdio.h>
#include <unistd.h>

extern ProtocolCmd g_cmd_buffer;
extern PersObjectCmd g_po_cmd_buffer;

void TEE_GetREETime(TEE_Time *time) {
  SocketStatus status = SocketStatusOk;

  if (!time) {
    return;
  }
  TEE_MemFill(&g_po_cmd_buffer, 0x00, sizeof(g_po_cmd_buffer));
  g_po_cmd_buffer.cmd_id = PROTOCOL_COMMAND_GETREETIME;
  g_po_cmd_buffer.data_len = sizeof(TEE_Time);

  struct sockaddr_un addr = { 0 };
  int sock_ = -1;

  addr.sun_family = AF_UNIX;
  snprintf(addr.sun_path, sizeof(addr.sun_path) - 1, "%u",
           g_cmd_buffer.service_data);

  status = OpenSocket(&addr, &sock_);

  if (SocketStatusOk != status) {
    goto exit;
  }

  status = WriteTimeData(sock_, &g_po_cmd_buffer);
  if (SocketStatusOk != status) {
    goto exit;
  }

  status = ReadTimeData(sock_, &g_po_cmd_buffer);
  if (SocketStatusOk != status) {
    goto exit;
  }

  if (TEE_SUCCESS != g_po_cmd_buffer.cmd_id) {
    status = SocketStatusError;
    goto exit;
  }

  TEE_MemMove(time, &g_po_cmd_buffer.data, min(sizeof(TEE_Time),
                                               g_po_cmd_buffer.data_len));
exit:
  if (sock_ >= 0) {
    close(sock_);
  }
  if (SocketStatusOk != status) {
    MB_LOGE("Panic reason: Get NWD Time error\n");
    TEE_Panic(0);
  }

}
// similar implementation for all platformes
TEE_Result TEE_Wait(uint32_t timeout) {
  struct timespec ts = { 0 };
  size_t timeout_nsec = (size_t)timeout * 1000 * 1000;
  size_t current_nsec = 0;
  size_t start_nsec = 0;

  if (!timeout) {
    return TEE_SUCCESS;
  }
  clock_gettime(CLOCK_REALTIME, &ts);
  start_nsec = ts.tv_sec * 1000 * 1000 * 1000 + ts.tv_nsec;

  do {
    if (TEE_GetCancellationFlag()) {
      return TEE_ERROR_CANCEL;
    }
    clock_gettime(CLOCK_REALTIME, &ts);
    current_nsec = ts.tv_sec * 1000 * 1000 * 1000 + ts.tv_nsec;
  } while (current_nsec - start_nsec < timeout_nsec);

  return TEE_SUCCESS;
}
