#include "CustomCommand.h"
#include "Application.h"
#include "LedController.h"
#include "MqttClient.h"
#include "esp_console.h"
#include <argtable3/argtable3.h>
#include <esp_log.h>
#include <iostream>

static int custom_command(int argc, char **argv) {
    printf("i am amass.\n");
    return 0;
}

static int led_command(int argc, char **argv) {
    for (int i = 0; i < argc; i++) {
        std::cout << i << " " << argv[i] << std::endl;
    }
    LedController::instance()->setDuty(static_cast<LedController::Channel>(atoi(argv[1])), atoi(argv[2]));
    return 0;
}

static int mqtt_command(int argc, char **argv) {
    MqttClient::instance()->initialize(argv[1], argv[2]);
    Application::instance()->setField("mqtt_username", std::string(argv[1]));
    Application::instance()->setField("mqtt_password", std::string(argv[2]));
    return 0;
}

static struct {
    struct arg_int *timeout;
    struct arg_str *ssid;
    struct arg_str *password;
    struct arg_end *end;
} join_args;

static int wifi_connect(int argc, char **argv) {
    int nerrors = arg_parse(argc, argv, (void **)&join_args);
    if (nerrors != 0) {
        arg_print_errors(stderr, join_args.end, argv[0]);
        return 1;
    }
    ESP_LOGI(__func__, "Connecting to '%s'", join_args.ssid->sval[0]);

    /* set default value*/
    if (join_args.timeout->count == 0) {
        join_args.timeout->ival[0] = Application::WifiJoinTimeoutMillisecond;
    }

    bool connected = Application::instance()->wifiConnect(join_args.ssid->sval[0], join_args.password->sval[0],
                                                          join_args.timeout->ival[0]);
    if (!connected) {
        ESP_LOGW(__func__, "Connection timed out");
        return 1;
    }
    Application::instance()->setField("ssid", std::string(join_args.ssid->sval[0]));
    Application::instance()->setField("psk", std::string(join_args.password->sval[0]));
    ESP_LOGI(__func__, "Connected");
    return 0;
}

void register_custom() {
    const esp_console_cmd_t heap_cmd = {
        .command = "amass",
        .help = "test command.",
        .hint = NULL,
        .func = &custom_command,
        .argtable = nullptr,
    };
    ESP_ERROR_CHECK(esp_console_cmd_register(&heap_cmd));

    join_args.timeout = arg_int0(NULL, "timeout", "<t>", "Connection timeout, ms");
    join_args.ssid = arg_str1(NULL, NULL, "<ssid>", "SSID of AP");
    join_args.password = arg_str0(NULL, NULL, "<pass>", "PSK of AP");
    join_args.end = arg_end(2);

    const esp_console_cmd_t join_cmd = {
        .command = "join",
        .help = "Join WiFi AP as a station",
        .hint = NULL,
        .func = &wifi_connect,
        .argtable = &join_args,
    };

    ESP_ERROR_CHECK(esp_console_cmd_register(&join_cmd));

    const esp_console_cmd_t led_cmd = {
        .command = "led",
        .help = "led pwm duty.",
        .hint = NULL,
        .func = &led_command,
        .argtable = nullptr,
    };
    ESP_ERROR_CHECK(esp_console_cmd_register(&led_cmd));

    const esp_console_cmd_t mqtt_cmd = {
        .command = "mqtt",
        .help = "mqtt client.",
        .hint = NULL,
        .func = &mqtt_command,
        .argtable = nullptr,
    };
    ESP_ERROR_CHECK(esp_console_cmd_register(&mqtt_cmd));
}