//
// Created by xajhu on 2021/7/5 0005.
//
#include <uv.h>
#include <zlog.h>
#include <unistd.h>

#include "init.h"
#include "config.h"
#include "misc.h"
#include "user_errno.h"
#include "task_manager.h"
#include "uthash/utstring.h"
#include "banner.h"
#include "inet_misc.h"
#include "crypto.h"
#include "hardware.h"
#include "msg_queue.h"
#include "http_svr.h"
#include "haywire.h"
#include "lib_config.h"
#include "prj_config.h"

#define DEFAULT_CONFIG_FILE ("vcpe.cfg")
#define DEFAULT_CONFIG_DIR  ("config")

static pid_t g_pid;
static int   g_isInited = FALSE;

static void catch_system_interupt(int UNUSED(sig_num)) {
    if (g_pid == uv_os_getpid()) {
        printf("\n");
        dzlog_warn("System close, clearing system resources..........\n\n");
        task_manager_exit();
        sleep(1);
    }
}

int user_init(const char *pAppCfgFile, const char *pCfgDirectory, const char *pKey, int logLevel) {
    int        ret;
    UT_string *pPath;
    char       bufCfgFile[MAX_PATH];
    char       bufCfgDir[MAX_PATH];

    g_pid = uv_os_getpid();

    signal(SIGINT, catch_system_interupt);
    signal(SIGABRT, catch_system_interupt);
    signal(SIGTERM, catch_system_interupt);
    signal(SIGQUIT, catch_system_interupt);
    signal(SIGTSTP, catch_system_interupt);
    signal(SIGHUP, catch_system_interupt);
    signal(SIGPIPE, SIG_IGN);

    // 初始化 libuv loop
    get_task_manager();

    memset(bufCfgDir, 0, MAX_PATH);
    memset(bufCfgFile, 0, MAX_PATH);

    if (pCfgDirectory == NULL) {
        sprintf(bufCfgDir, "%s/%s", get_cur_process_dir(), DEFAULT_CONFIG_DIR);
    } else {
        strcpy(bufCfgDir, pCfgDirectory);
    }

    if (pAppCfgFile == NULL) {
        const char *pTmp = strdup(bufCfgDir);
        sprintf(bufCfgFile, "%s/%s", pTmp, DEFAULT_CONFIG_FILE);
        free((void *)pTmp);
    } else {
        strcpy(bufCfgFile, pAppCfgFile);
    }

    // 初始化zlog库,系统集成日志功能
    utstring_new(pPath);
    utstring_printf(pPath, "%s/%s", bufCfgDir, "zlog.conf");

    if ((ret = dzlog_init(utstring_body(pPath), get_cur_process_name())) != ERR_SUCCESS) {
        printf("Zlog configure file [%s] init result: %d+++++\n", utstring_body(pPath), ret);
        zlog_profile();
        return -ERR_ZLOG_INIT;
    } else {
        dzlog_info("Zlog used configure file [%s]\n", utstring_body(pPath));
    }

    zlog_level_switch(zlog_get_category(get_cur_process_name()),
                      logLevel > ZLOG_LEVEL_DEBUG ? logLevel : ZLOG_LEVEL_DEBUG);

    utstring_free(pPath);

    // 处置化配置文件库,系统集成配置文件支持功能
    dzlog_info("System used configure file [%s]\n", bufCfgFile);
    if ((ret = init_config_system(bufCfgFile, pKey)) != ERR_SUCCESS) {
        dzlog_error("Load system configuration error: %d\n", ret);
        return -ERR_CONFIG_INIT;
    }

    dzlog_info("%s library version %s information: %s (Build: %s %s  GCC Ver:%s) With %lu(bits) OS\n",
               VCPE_LIB_NAME,
               VCPE_LIB_VER,
               VCPE_GIT_VERSION,
               __DATE__,
               __TIME__,
               __VERSION__,
               sizeof(int *) * 8);

    if (cfg_get_banner_enable()) {
        banner_show();
    }

    evp_system_init();
    inet_api_init();

    if (cfg_get_hardware_watch_enable()) {
        init_hardware();
    }

    if ((ret = mq_init()) != ERR_SUCCESS) {
        dzlog_error("Message queue init error: %d\n", ret);
    }

    if ((ret = mq_data_init()) != ERR_SUCCESS) {
        dzlog_error("Message queue init error: %d\n", ret);
    }

    http_svr_init();

    g_isInited = TRUE;

    return ERR_SUCCESS;
}

void user_uninit() {
    if (g_isInited) {
        task_manager_exit();
        free_http_server();
        mq_uninit();
        zlog_fini();
        uninit_config_system();
        uv_loop_close(get_task_manager());
    }
}