#include "task_descriptor.h"

#include "task_descriptor_map.h"
#include "driver_log.h"

#include <tee_internal_api.h>

/**
 * @brief Maximal number of retries to find object in pa kernel tasks table
 */
static const uint16_t kFindTaskDescrAttempts = 100;

/**
 * @brief Perform lookup with retries in proca table
 * @param [in] map Kernel hash table configuration
 * @param [in] key Search key
 * @param [out] out_descr Output task descriptor structure
 * @return ::PA_TZ_SUCCESS in case of success, ::PA_TZ_GENERAL_ERROR
 */
static PaTzResult PaTaskDescrFindInMap(const TaskDescriptorMap *map,
                                       const void *key,
                                       TaskDescriptor *out_descr);

static PaTzResult PaTaskDescrFindInMap(const TaskDescriptorMap *map,
                                       const void *key,
                                       TaskDescriptor *out_descr) {
  PaTzResult result;

  for (uint16_t attempt = 0; attempt < kFindTaskDescrAttempts; ++attempt) {
      result = TaskDescriptorMapFind(map, key, out_descr);
      if (result != PA_TZ_SUCCESS && result != PA_TZ_AF_TASK_IS_NOT_FOUND) {
        LOG_E("Task descriptor search error.\n");
        return result;
      }
      if (result == PA_TZ_AF_TASK_IS_NOT_FOUND) {
        TEE_Wait(1);
      } else {
        break;
      }
  }

  if (result != PA_TZ_SUCCESS) {
    LOG_W("Failed to find task descriptor in proca table map.\n");
    LOG_D("Hash table name: %s table.\n", map->map_name);
    return result;
  }

  return PA_TZ_SUCCESS;
}

PaTzResult TaskDescriptorFindByPid(uint32_t pid,
                                        TaskDescriptor *out_descr) {
  return PaTaskDescrFindInMap(GetPidMap(), &pid, out_descr);
}

PaTzResult TaskDescriptorFindByAppName(const char *app_name_str,
                                       const size_t app_name_size,
                                       TaskDescriptor *out_descr) {
  ApplicationName app_name = {
    .app_name = app_name_str,
    .app_name_size = app_name_size
  };
  return PaTaskDescrFindInMap(GetAppNameMap(), &app_name, out_descr);
}
