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

#include "esp_log.h"
#include "nvs_flash.h"

#include "freertos/FreeRTOS.h"
#include "freertos/task.h"

#include "utils.h"
#include "command.h"
#include "cmd_system.h"

/* Module headers */
#ifdef CONFIG_MODULE_NETWORK
#include "cmd_network.h"
#endif

#ifdef CONFIG_MODULE_FAKEAP
#include "cmd_fakeAP.h"
#endif

#ifdef CONFIG_MODULE_RECON
#include "cmd_recon.h"
#endif

static const char *TAG = "MAIN";

static esp_log_level_t espilon_log_level_from_kconfig(void)
{
#if defined(CONFIG_ESPILON_LOG_LEVEL_ERROR)
    return ESP_LOG_ERROR;
#elif defined(CONFIG_ESPILON_LOG_LEVEL_WARN)
    return ESP_LOG_WARN;
#elif defined(CONFIG_ESPILON_LOG_LEVEL_INFO)
    return ESP_LOG_INFO;
#elif defined(CONFIG_ESPILON_LOG_LEVEL_DEBUG)
    return ESP_LOG_DEBUG;
#elif defined(CONFIG_ESPILON_LOG_LEVEL_VERBOSE)
    return ESP_LOG_VERBOSE;
#else
    return ESP_LOG_INFO;
#endif
}

static void espilon_log_init(void)
{
    esp_log_level_set("*", espilon_log_level_from_kconfig());
#ifdef CONFIG_ESPILON_LOG_BOOT_SUMMARY
    ESPILON_LOGI_PURPLE(TAG, "===== BOOT SUMMARY =====");
#endif
}

static void init_nvs(void)
{
    esp_err_t ret = nvs_flash_init();
    if (ret == ESP_ERR_NVS_NO_FREE_PAGES ||
        ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {

        ESP_ERROR_CHECK(nvs_flash_erase());
        ESP_ERROR_CHECK(nvs_flash_init());
    }
}

void app_main(void)
{
    espilon_log_init();
    ESP_LOGI(TAG, "Booting system");

    init_nvs();

    /* =====================================================
     * Command system
     * ===================================================== */

    command_async_init();          // Async worker (Core 1)
    mod_system_register_commands();

    /* Register enabled modules */
#ifdef CONFIG_MODULE_NETWORK
    mod_network_register_commands();
    ESPILON_LOGI_PURPLE(TAG, "Network module loaded");
#endif

#ifdef CONFIG_MODULE_FAKEAP
    mod_fakeap_register_commands();
    ESPILON_LOGI_PURPLE(TAG, "FakeAP module loaded");
#endif

#ifdef CONFIG_MODULE_RECON
    #ifdef CONFIG_RECON_MODE_CAMERA
    mod_camera_register_commands();
    ESPILON_LOGI_PURPLE(TAG, "Camera module loaded");
    #endif
    #ifdef CONFIG_RECON_MODE_MLAT
    mod_mlat_register_commands();
    ESPILON_LOGI_PURPLE(TAG, "MLAT module loaded");
    #endif
#endif

    command_log_registry_summary();

    /* =====================================================
     * Network backend
     * ===================================================== */
    vTaskDelay(pdMS_TO_TICKS(1200));
    if (!com_init()) {
        ESP_LOGE(TAG, "Network backend init failed");
        return;
    }

    ESP_LOGI(TAG, "System ready");
}
