// 用于测试
#include "errmsgBridge.h"

#ifdef USE_SGX

#include <stdio.h>
#include <string.h>
#include <assert.h>

#include <unistd.h>
#include <pwd.h>
#include <stdlib.h>
#include <algorithm>
#define MAX_PATH FILENAME_MAX

#include <sgx_urts.h>
#include <sgx_uswitchless.h>

#include "App.h"


#include "Singleton.h"
#include "Enclave_u.h"


extern "C" {
#include "postgres.h"

}


/* Global EID shared by multiple threads */
sgx_enclave_id_t global_eid = 0;



typedef struct _sgx_errlist_t
{
    sgx_status_t err;
    const char *msg;
    const char *sug; /* Suggestion */
} sgx_errlist_t;

/* Error code returned by sgx_create_enclave */
static sgx_errlist_t sgx_errlist[] = {
    {SGX_ERROR_UNEXPECTED,
     "SGX: Unexpected error occurred.",
     NULL},
    {SGX_ERROR_INVALID_PARAMETER,
     "SGX: Invalid parameter.",
     NULL},
    {SGX_ERROR_OUT_OF_MEMORY,
     "SGX: Out of memory.",
     NULL},
    {SGX_ERROR_ENCLAVE_LOST,
     "SGX: Power transition occurred.",
     "SGX: Please refer to the sample \"PowerTransition\" for details."},
    {SGX_ERROR_INVALID_ENCLAVE,
     "SGX: Invalid enclave image.",
     NULL},
    {SGX_ERROR_INVALID_ENCLAVE_ID,
     "SGX: Invalid enclave identification.",
     NULL},
    {SGX_ERROR_INVALID_SIGNATURE,
     "SGX: Invalid enclave signature.",
     NULL},
    {SGX_ERROR_OUT_OF_EPC,
     "SGX: Out of EPC memory.",
     NULL},
    {SGX_ERROR_NO_DEVICE,
     "SGX: Invalid SGX device.",
     "SGX: Please make sure SGX module is enabled in the BIOS, and install SGX driver afterwards."},
    {SGX_ERROR_MEMORY_MAP_CONFLICT,
     "SGX: Memory map conflicted.",
     NULL},
    {SGX_ERROR_INVALID_METADATA,
     "SGX: Invalid enclave metadata.",
     NULL},
    {SGX_ERROR_DEVICE_BUSY,
     "SGX: SGX device was busy.",
     NULL},
    {SGX_ERROR_INVALID_VERSION,
     "SGX: Enclave version was invalid.",
     NULL},
    {SGX_ERROR_INVALID_ATTRIBUTE,
     "SGX: Enclave was not authorized.",
     NULL},
    {SGX_ERROR_ENCLAVE_FILE_ACCESS,
     "SGX: Can't open enclave file.",
     NULL},
    {SGX_ERROR_NDEBUG_ENCLAVE,
     "SGX: The enclave is signed as product enclave, and can not be created as debuggable enclave. ",
     NULL}};

/* Check error conditions for loading enclave */
void print_error_message(sgx_status_t ret)
{
    size_t idx = 0;
    size_t ttl = sizeof sgx_errlist / sizeof sgx_errlist[0];

    for (idx = 0; idx < ttl; idx++)
    {
        if (ret == sgx_errlist[idx].err)
        {
            if (NULL != sgx_errlist[idx].sug)
                printf("Info: %s\n", sgx_errlist[idx].sug);
            printf("Error: %s\n", sgx_errlist[idx].msg);
            break;
        }
    }

    if (idx == ttl)
        printf("Error code is 0x%X. Please refer to the \"Intel SGX SDK Developer Reference\" for more details.\n", ret);
}

int initialize_enclave(void)
{
    sgx_status_t ret = SGX_ERROR_UNEXPECTED;  // 初始化错误状态
    /* 调用 sgx_create_enclave 来初始化一个信任域实例 */
    /* 调试支持：将第二个参数设置为 1 */   
    ret = sgx_create_enclave(ENCLAVE_FILENAME, SGX_DEBUG_FLAG, NULL, NULL, &global_eid, NULL);
    if (ret != SGX_SUCCESS) {  // 如果初始化失败，打印错误信息
        print_error_message(ret);
        return -1;  // 返回错误状态
    }
    return 0;  // 成功初始化，返回0
}

/* Application entry */
// int SGX_CDECL main(int argc, char *argv[])
// {
//     (void)(argc);
//     (void)(argv);
//     // int pid = fork();
//     /* Initialize the enclave */
//     if (initialize_enclave() < 0)
//     {
//         printf("Init Enclave Error. \n");
//         // getchar();
//         return -1;
//     }
//     printf("Init Enclave Succ. \n");
//     /* Destroy the enclave */
//     sgx_destroy_enclave(global_eid);
//     sleep(1);
//     return 0;
// }

#else

#include "App.h"

#endif

#include "errmsgBridge.h"
#include "LogBase.h"

void ocall_ereport(const char *str) {
    util::Log(str, util::log::error);

}

void ocall_usleep(size_t us) {
    usleep(us);
}

// 新增：读取DEK文件的OCALL实现
// 这个函数被SGX enclave调用，用于读取宿主机上的DEK文件
// 参数：
//   filename: DEK文件路径（通常是"/etc/encryptsql/dek.sealed"）
//   buffer: 用于存储DEK内容的缓冲区
//   max_size: 缓冲区的最大大小
//   actual_size: 实际读取的字节数
// 返回值：
//   0: 成功
//   -1: 失败
void ocall_read_dek(const char* filename, char* buffer, size_t max_size, size_t* actual_size) {
    if (!filename || !buffer || !actual_size || max_size == 0) {
        printf("Error: Invalid parameters for ocall_read_dek_file\n");
    }
    
    FILE* file = fopen(filename, "rb");
    if (!file) {
        printf("Error: Failed to open DEK file: %s\n", filename);
        *actual_size = 0;
    }
    
    // 获取文件大小
    fseek(file, 0, SEEK_END);
    long file_size = ftell(file);
    fseek(file, 0, SEEK_SET);
    
    if (file_size < 0) {
        printf("Error: Failed to get file size for: %s\n", filename);
        fclose(file);
        *actual_size = 0;
    }
    
    if (file_size > (long)max_size) {
        printf("Error: DEK file too large: %ld bytes (max: %zu)\n", file_size, max_size);
        fclose(file);
        *actual_size = 0;
    }
    
    if (file_size == 0) {
        printf("Warning: DEK file is empty: %s\n", filename);
        fclose(file);
        *actual_size = 0;
    }
    
    // 读取文件内容
    size_t bytes_read = fread(buffer, 1, file_size, file);
    fclose(file);
    
    if (bytes_read != (size_t)file_size) {
        printf("Error: Failed to read complete DEK file: %s (read %zu of %ld bytes)\n", 
               filename, bytes_read, file_size);
        *actual_size = 0;
    }
    
    *actual_size = bytes_read;
    printf("Successfully read DEK file: %s, size: %zu bytes\n", filename, bytes_read);
}
