/**
 * @file webserver.cpp
 * @author Radim Buráň (xburan03@stud.fit.vutbr.cz)
 */

#include "webserver.hpp"

httpd_handle_t serverHandle = NULL;

httpd_uri_t uri_restart = {
    .uri      = "/restart",
    .method   = HTTP_GET,
    .handler  = restart_handler,
    .user_ctx = NULL
};

httpd_uri_t uri_get = {
    .uri      = "/",
    .method   = HTTP_GET,
    .handler  = get_handler,
    .user_ctx = NULL
};

httpd_uri_t uri_post = {
    .uri      = "/",
    .method   = HTTP_POST,
    .handler  = post_handler,
    .user_ctx = NULL
};

const char* response_get_data = R"rawliteral(<!DOCTYPE HTML><html><head> <meta charset="utf8" name="viewport" content="width=device-width"> <title>Nastavení květináče</title></head><style>* { font-family: Arial, Helvetica, sans-serif;}input { width: 100%; box-sizing: border-box; border: none; border-radius: 5px; padding: 10px 10px}input[type=submit] { width: 100%; background-color: #4caf50; margin-top: 8px; cursor: pointer}input[type=submit]:hover { background-color: #419645; color: #fff}.center { margin: 0; position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%)}.paper { background-color:#efefef; border-radius: 5px; padding: 10px; margin: 5px;}.title { margin: 3px 0px; font-weight: bold;}</style><body class="center"><div style="width: 300px"> <div class="paper"> <p class="title">Nastavení ID květináče:</p> <form action="/" method="post"> <label for="dev_id">ID květináče:</label><br> <input type="text" id="dev_id" name="dev_id" required placeholder="ID květináče z webu"><br> <input type="submit" value="Uložit ID"> </form> </div> <div class="paper"> <p class="title">Nastavení WiFi:</p> <form action="/" method="post"> <label for="ssid">SSID:</label><br> <input type="text" id="ssid" name="ssid" required placeholder="Název WiFi sítě"><br> <label for="pwd">Heslo:</label><br> <input type="password" id="pwd" name="pwd" placeholder="Ponechat prázdné pro wifi bez hesla"><br> <input type="submit" value="Uložit WiFi"></form></div><form action="/restart" method="get" id="resetform"><input type="submit" value="Restartovat"></form></div></body></html>)rawliteral";

const char* response_post_data = "";

esp_err_t restart_handler(httpd_req_t* req) {
    ESP_LOGI(LOG_TAG, "Restart!");
    httpd_resp_send(req, "Restarting!", HTTPD_RESP_USE_STRLEN);
    esp_restart();
    return ESP_OK;
}

esp_err_t sendResponse(httpd_req_t *req) {
    httpd_resp_send_chunk(req, response_get_data, HTTPD_RESP_USE_STRLEN);
    httpd_resp_send_chunk(req, "<script>", HTTPD_RESP_USE_STRLEN);

    char* partEnd = "\";\0";
    char* partStart = NULL;
    char* res = NULL;

    char* devID = readString("devid");
    if (devID != NULL) {
        partStart = "document.getElementById(\"dev_id\").value=\"";
        res = (char*) malloc(strlen(partStart) + strlen(devID) + strlen(partEnd) + 1);
        strcpy(res, partStart);
        strcat(res, devID);
        free(devID);
        strcat(res, partEnd);

        httpd_resp_send_chunk(req, res, HTTPD_RESP_USE_STRLEN);
        free(res);
    }

    char* ssid = readString("ssid");
    if (ssid != NULL) {
        partStart = "document.getElementById(\"ssid\").value=\"";
        res = (char*) malloc(strlen(partStart) + strlen(ssid) + strlen(partEnd) + 1);
        strcpy(res, partStart);
        strcat(res, ssid);
        free(ssid);
        strcat(res, partEnd);

        httpd_resp_send_chunk(req, res, HTTPD_RESP_USE_STRLEN);
        free(res);
    }

    httpd_resp_send_chunk(req, "</script>", HTTPD_RESP_USE_STRLEN);
    return httpd_resp_send_chunk(req, NULL, 0);    //to finish the chunk sending
}

esp_err_t get_handler(httpd_req_t *req) {
    ESP_LOGI(LOG_TAG, "getHandler -> sending response...");
    return sendResponse(req);
}

char* find_value(const char* key, const char* buffer) {
    size_t size = 64;
    char* res = (char*)malloc(size + 1);
    esp_err_t err = httpd_query_key_value(buffer, key, res, size);
    if (err != ESP_OK) {
        return NULL;
    }
    res[size] = '\0';
    return res;
}

/**
 * @param req request
 * @return char* content or null | must free!
 */
char* receiveContent(httpd_req_t *req) {
    char* content = (char*)malloc(req->content_len + 1);
    int ret = httpd_req_recv(req, content, req->content_len);
    if (ret <= 0) {
        if (ret == HTTPD_SOCK_ERR_TIMEOUT) {
            httpd_resp_send_408(req);
        }
        return NULL;
    }
	content[req->content_len] = '\0';
	ESP_LOGI(LOG_TAG, "receiveContent -> content=[%s]", content);
    return content;
}

esp_err_t post_handler(httpd_req_t *req) {
    char* content = receiveContent(req);
    if (content == NULL) {
        return ESP_FAIL;
    }
    ESP_LOGI(LOG_TAG, "Content -> [%s]", content);
    
    char* ssid = find_value("ssid", content);
    char* pwd = find_value("pwd", content);
    char* devID = find_value("dev_id", content);
    
    free(content);

    if (ssid != NULL) {
        ESP_LOGI(LOG_TAG, "SSID: [%s] | PWD: [%s]", ssid, pwd);

        writeString("ssid", ssid);
        writeString("pwd", pwd);

        free(ssid);
        free(pwd);
    }

    if (devID != NULL) {
        ESP_LOGI(LOG_TAG, "ID: [%s]", devID);

        writeString("devid", devID);
        writeU64("pump_t", 0);

        free(devID);
    }

    return sendResponse(req);
}

void webServerStart() {
    httpd_config_t config = HTTPD_DEFAULT_CONFIG();

    if (httpd_start(&serverHandle, &config) == ESP_OK) {
        ESP_LOGI(LOG_TAG, "Web server started...adding handlers!");
        httpd_register_uri_handler(serverHandle, &uri_get);
        httpd_register_uri_handler(serverHandle, &uri_post);
        httpd_register_uri_handler(serverHandle, &uri_restart);
    }

    gpio_set_level(LED_PIN, 1);
}

void webServerStop() {
    if (serverHandle != NULL) {
        httpd_stop(serverHandle);
    }
    
    gpio_set_level(LED_PIN, 0);
}
    

