//
// Created by xajhu on 2021/6/29 0029.
//
#include <uv.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include "cmdline.h"
#include "task_manager.h"
#include "init.h"
#include "inet_misc.h"
#include "config.h"
#include "zlog_module.h"

#include "prj_config.h"
#include "user_errno.h"

#ifdef LWIP_ON
#include "user_info.h"
#include "lwip/tcpip.h"
#endif

#include "proto.h"

#ifdef OPENDHCPDDNS_ON
#include "dual_server/dualsvr.h"
#endif

#ifdef LWIP_ON
static void test_init(void *arg) { /* remove compiler warning */
    sys_sem_t *init_sem;

    init_sem = (sys_sem_t *)arg;

    srand((unsigned int)time(0));

    sys_sem_signal(init_sem);
}

static void lwip_init_env() {
    err_t     err;
    sys_sem_t init_sem;

    err = sys_sem_new(&init_sem, 0);
    LWIP_UNUSED_ARG(err);
    tcpip_init(test_init, &init_sem);
    sys_sem_wait(&init_sem);
    sys_sem_free(&init_sem);
}
#endif

cJSON *create_app_process_status(int isStart) {
    cJSON *pRspMsg = cJSON_CreateObject();
#ifdef USERVNI_ON
    cJSON_AddNumberToObject(pRspMsg, "vni", cfg_get_user_vni_id());
#endif
    cJSON_AddStringToObject(pRspMsg, "process", isStart ? "setup" : "exit");
    return pRspMsg;
}

static void on_http_response_cb(void        *pData,
                                unsigned int size,
                                const char  *pReqUrl,
                                const char  *pDlPath,
                                const char  *pTaskUuid,
                                int          iFinished,
                                void        *pUserData) {
    if (iFinished == 0) {
        LOG_MOD(debug, ZLOG_MOD_MAIN, "Request(%s): [%s] Response: [%u] OK:\n", pTaskUuid, pReqUrl, size);
    } else if (iFinished == 1) {
        LOG_MOD(error, ZLOG_MOD_MAIN, "Request(%s): [%s] Response: [%u] Error\n", pTaskUuid, pReqUrl, size);
    } else {
        LOG_MOD(error, ZLOG_MOD_MAIN, "Download Error Code: %d\n", iFinished);
    }

    free(pUserData);
}

int main(int argc, char **argv) {
    int         ret;
    const char *pRspUrl;

#ifdef OPENDHCPDDNS_ON
    return dual_server_main(argc, argv);
#else
    uv_setup_args(argc, argv);

    printf("Application %s version %s\n", VCPE_PROJECT_NAME, VCPE_PROJECT_VER);

    setvbuf(stdout, NULL, _IONBF, 0);

    ret = menu_run(argc, argv);

    if (ret == ERR_MENU_EXIT) {
        user_uninit();
        exit(0);
    } else if (ret != ERR_SUCCESS) {
        printf("Application setup error(%d), please used --help to show usage, exited!!!\n", ret);
        user_uninit();
        exit(0);
    }

#ifdef LWIP_ON
    lwip_init_env();
#endif

#ifdef PPPOE_ON
    user_info_init();
    pppoe_session_init();
#endif

    pRspUrl = config_get_agent_moniter_report_url();

    if (pRspUrl && strlen(pRspUrl) > 0) {
        const char *pStrSetup = proto_create_new(create_app_process_status(1), 200);
        inet_http_post_async(config_get_agent_moniter_report_url(), pStrSetup, on_http_response_cb, (void *)pStrSetup);
    }

    task_manager_run();

    if (pRspUrl && strlen(pRspUrl) > 0) {
        const char *pStrExit = proto_create_new(create_app_process_status(0), 200);
        inet_http_post_async(config_get_agent_moniter_report_url(), pStrExit, on_http_response_cb, (void *)pStrExit);
    }

    while (!is_system_cleanup()) {
        sleep(1);
    }

    user_uninit();

    return ret;
#endif
}