#include "sync_response.h"

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

const static char *TAG = "sync_response";

sync_response *sync_response_parse(cJSON *res)
{
    // Parse relays information
    cJSON *relays_json = cJSON_GetObjectItem(res, "relays");
    if (relays_json == NULL)
    {
        ESP_LOGE(TAG, "Missing relays status in sync response!");
        return NULL;
    }

    int relays_size = cJSON_GetArraySize(relays_json);
    sync_response *sync_res = calloc(1, sizeof(sync_response) + relays_size * sizeof(bool));

    if (!sync_res)
    {
        ESP_LOGE(TAG, "Failed to allocate memory to store synchronization response!");
        return NULL;
    }

    sync_res->len = relays_size;

    for (int i = 0; i < sync_res->len; i++)
    {
        sync_res->relays[i] = false;

        cJSON *item = cJSON_GetArrayItem(relays_json, i);
        assert(item != NULL);
        cJSON *enabled = cJSON_GetObjectItem(item, "enabled");

        if (enabled == NULL)
        {
            ESP_LOGE(TAG, "At least a relay is missing the enabled field. Assuming false.");
            continue;
        }

        if (cJSON_IsTrue(enabled))
        {
            sync_res->relays[i] = true;
        }
    }

    // Parse firmware update information
    cJSON *update = cJSON_GetObjectItem(res, "available_update");
    if (update != NULL)
    {
        char *val = cJSON_GetStringValue(update);
        sync_res->available_update = val != NULL ? strdup(val) : NULL;
    }

    return sync_res;
}

void sync_response_print(sync_response *res)
{
    ESP_LOGI(TAG, " === sync response begin === ");

    if (res->available_update != NULL)
    {
        ESP_LOGI(TAG, "> AVAILABLE UPDATE! Version %s", res->available_update);
    }

    ESP_LOGI(TAG, "# of relays: %d", res->len);
    for (size_t i = 0; i < res->len; i++)
        ESP_LOGI(TAG, "Relay[%d]=%s", i, res->relays[i] ? "ON" : "off");
    ESP_LOGI(TAG, " === sync response end === ");
}

void sync_response_free(sync_response *res)
{
    if (res == NULL)
        return;

    if (res->available_update != NULL)
        free(res->available_update);

    free(res);
}

bool sync_response_is_relay_on(sync_response *res, int relay_number)
{
    if (res->len <= relay_number)
    {
        ESP_LOGW(TAG, "Requested state of an unconfigured relay (%d). Defaulting to off.", relay_number);
        return false;
    }

    return res->relays[relay_number];
}