#include <string.h>
#include <errno.h>

#include <mongoose.h>
#include <logger.h>
#include <handlers.h>
#include <status.h>
#include <models/controller.h>
#include <models/relay.h>

static void
handle_mqtt_publish_controller(char **topic_save, int controller_id, const char *payload)
{
    (void)controller_id;
    (void)payload;
    char *topic_token = strtok_r(NULL, "/", topic_save);
    if(!topic_token)
    {
        return;
    }
    if(strcmp(topic_token, "relay") == 0)
    {
        char *relay_num_str = strtok_r(NULL, "/", topic_save);
        if(!relay_num_str)
        {
            return;
        }
        errno = 0;
        int relay_num = strtol(relay_num_str, NULL, 10);
        if(errno)
        {
            return;
        }
        int relay_id = relay_get_id_for_controller(controller_id, relay_num);
        if(!relay_id)
        {
            return;
        }
        status_update_entry(relay_id, payload[0] == '1');
    }
}

static void
handle_mqtt_publish(struct mg_mqtt_message *msg)
{
    char *topic = malloc(sizeof(char) * (msg->topic.len + 1));
    strncpy(topic, msg->topic.p, msg->topic.len);
    topic[msg->topic.len] = '\0';
    LOGGER_DEBUG("received mqtt publish for topic %s\n", topic);

    char *payload = malloc(sizeof(char) * (msg->payload.len + 1));
    strncpy(payload, msg->payload.p, msg->payload.len);
    payload[msg->payload.len] = '\0';

    char *topic_save_null = NULL;
    char **topic_save = &topic_save_null;
    char *topic_token = strtok_r(topic, "/", topic_save);
    if(topic_token)
    {
        if(strcmp(topic_token, "controller") == 0)
        {
            char *controller_uid_str = strtok_r(NULL, "/", topic_save);
            uuid_t controller_uid;
            if(uuid_parse(controller_uid_str, controller_uid) == 0)
            {
                int controller_id = controller_get_id_for_uid(controller_uid);
                if(controller_id)
                {
                    handle_mqtt_publish_controller(topic_save, controller_id, payload);
                }
            }
        }
    }

    free(payload);
    free(topic);
}

void
handler_mqtt(struct mg_connection *nc, int ev, void *p)
{
    if(ev == MG_EV_POLL)
    {
        return;
    }

    mg_mqtt_broker(nc, ev, p);
    if(ev == MG_EV_MQTT_PUBLISH)
    {
        struct mg_mqtt_message *msg = (struct mg_mqtt_message*)p;
        handle_mqtt_publish(msg);
    }
}