#include "wifi.hpp"
#include <logger.h>

WiFiManager wm;
extern Config config;
extern logging::Logger logger;
// Flag for saving data
bool shouldSaveConfig = false;

// Variables to hold data from custom textboxes
char testString[50] = "test value";
int testNumber = 1234;
char mqtt_server[40];
int mqtt_port = 1883;
char mqtt_username[34] = "";
char mqtt_password[34] = "";
char mqtt_topic[34] = "";

void setupWifi(const char *setupWifi, bool resetOnStart)
{
    // Change to true when testing to force configuration every time we run
    bool forceConfig = false;
    wm.setConfigPortalTimeout(60);
    // Reset settings (only for development)
    if (resetOnStart)
    {
        wm.resetSettings();
    }

    // Set config save notify callback
    wm.setSaveConfigCallback(saveConfigCallback);

    // Set callback that gets called when connecting to previous WiFi fails, and enters Access Point mode
    wm.setAPCallback(configModeCallback);

    // Custom elements
    WiFiManagerParameter custom_mqtt_server("server", "mqtt server", mqtt_server, 40);
    WiFiManagerParameter custom_mqtt_username("username", "mqtt username", mqtt_username, 50);
    WiFiManagerParameter custom_mqtt_password("password", "mqtt password", mqtt_password, 50);
    WiFiManagerParameter custom_mqtt_topic("topic", "mqtt topic", mqtt_topic, 50);

    // Text box (String) - 50 characters maximum
    WiFiManagerParameter custom_text_box("key_text", "Enter your string here", testString, 50);

    // Need to convert numerical input to string to display the default value.
    char convertedValue[6];
    sprintf(convertedValue, "%d", testNumber);

    // Text box (Number) - 7 characters maximum
    WiFiManagerParameter custom_text_box_num("key_num", "Enter your number here", convertedValue, 7);
    char convertedMqttPort[6];
    sprintf(convertedMqttPort, "%d", mqtt_port);
    WiFiManagerParameter custom_mqtt_port("port", "mqtt port", convertedMqttPort, 6);

    // Add all defined parameters
    wm.addParameter(&custom_text_box);
    wm.addParameter(&custom_text_box_num);
    wm.addParameter(&custom_mqtt_server);
    wm.addParameter(&custom_mqtt_port);
    wm.addParameter(&custom_mqtt_username);
    wm.addParameter(&custom_mqtt_password);
    wm.addParameter(&custom_mqtt_topic);

    if (forceConfig)
    // Run if we need a configuration
    {
        if (!wm.startConfigPortal(setupWifi))
        {
            logger.log(logging::LoggerLevel::LOGGER_LEVEL_WARN, "Wifi", "failed to connect and hit timeout");
            delay(3000);
            // reset and try again, or maybe put it to deep sleep
            ESP.restart();
            delay(5000);
        }
    }
    else
    {
        if (!wm.autoConnect(setupWifi))
        {
            logger.log(logging::LoggerLevel::LOGGER_LEVEL_WARN, "Wifi", "failed to connect and hit timeout");
            delay(3000);
            // if we still have not connected restart and try all over again
            ESP.restart();
            delay(5000);
        }
    }

    // If we get here, we are connected to the WiFi

    logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "Wifi", "");
    logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "Wifi", "WiFi connected");
    String message = "IP address: " + String(WiFi.localIP());
    logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "Wifi", message.c_str());

    // Lets deal with the user config values

    // Copy the string value
    strncpy(testString, custom_text_box.getValue(), sizeof(testString));
    Serial.print("testString: ");
    Serial.println(testString);

    // Convert the number value
    testNumber = atoi(custom_text_box_num.getValue());
    Serial.print("testNumber: ");
    Serial.println(testNumber);

    mqtt_port = atoi(custom_mqtt_port.getValue());
    strncpy(mqtt_server, custom_mqtt_server.getValue(), sizeof(mqtt_server));
    strncpy(mqtt_username, custom_mqtt_username.getValue(), sizeof(mqtt_username));
    strncpy(mqtt_password, custom_mqtt_password.getValue(), sizeof(mqtt_password));
    strncpy(mqtt_topic, custom_mqtt_topic.getValue(), sizeof(mqtt_topic));

    
    // Save the custom parameters to FS
    if (shouldSaveConfig)
    {
        logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "Wifi", "Save config");
        saveConfigFile();
    }
}

void saveConfigCallback()
// Callback notifying us of the need to save configuration
{
    logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "Wifi", "Should save config");
    shouldSaveConfig = true;
}

void configModeCallback(WiFiManager *myWiFiManager)
// Called when config mode launched
{
    logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "Wifi", "Entered Configuration Mode");
    
    String message = "Config SSID: " + String(myWiFiManager->getConfigPortalSSID());
    logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "Wifi", message.c_str());

    
    message = "Config IP Address: " + String(WiFi.softAPIP());
    logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "Wifi", message.c_str());
}

void saveConfigFile()
// Save Config in JSON format
{
    logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "Wifi", "Saving configuration...");
    config.setMqttConfig(mqtt_server, mqtt_port, mqtt_username, mqtt_password, mqtt_topic);
    config.writeData();
}
