/*
 * Copyright 2017, Data61
 * Commonwealth Scientific and Industrial Research Organisation (CSIRO)
 * ABN 41 687 119 230.
 *
 * This software may be distributed and modified according to the terms of
 * the BSD 2-Clause license. Note that NO WARRANTY is provided.
 * See "LICENSE_BSD2.txt" for details.
 *
 * @TAG(DATA61_BSD)
 */

#include <utils/sglib.h>
#include <platsupport/tqueue.h>

static int cmp(uint64_t a, uint64_t b)
{
     if (a > b) {
         return 1;
     } else if (a < b) {
         return -1;
     } else {
         return 0;
     }
}

#define TIMEOUT_CMP(t1, t2) (cmp(t1->timeout.abs_time, t2->timeout.abs_time))

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-variable"
SGLIB_DEFINE_SORTED_LIST_PROTOTYPES(tqueue_node_t, TIMEOUT_CMP, next)
SGLIB_DEFINE_SORTED_LIST_FUNCTIONS(tqueue_node_t, TIMEOUT_CMP, next)
#pragma GCC diagnostic pop

static tqueue_node_t *head(tqueue_node_t *list)
{
    struct sglib_tqueue_node_t_iterator it;
    return sglib_tqueue_node_t_it_init(&it, list);
}

int tqueue_alloc_id(tqueue_t *tq, unsigned int *id)
{
    if (!tq || !id) {
        return EINVAL;
    }

    for (int i = 0; i < tq->n; i++) {
        if (!tq->array[i].allocated) {
            tq->array[i].allocated = true;
            *id = i;
            return 0;
        }
    }

    ZF_LOGE("Out of timer client ids\n");
    return ENOMEM;
}

int tqueue_alloc_id_at(tqueue_t *tq, unsigned int id)
{
    if (!tq || id >= tq->n) {
        return  EINVAL;
    }

    if (tq->array[id].allocated) {
        return EADDRINUSE;
    }

    tq->array[id].allocated = true;
    return 0;
}

int tqueue_free_id(tqueue_t *tq, unsigned int id)
{
    if (!tq) {
        return EINVAL;
    }

    if (id < 0 || id >= tq->n) {
        ZF_LOGE("Invalid id");
        return EINVAL;
    }

    if (!tq->array[id].allocated) {
        ZF_LOGW("Freeing unallocated id");
        return EINVAL;
    }

    /* remove from queue */
    if (tq->array[id].active) {
        sglib_tqueue_node_t_delete(&tq->queue, &tq->array[id]);
        tq->array[id].active = false;
    }

    tq->array[id].allocated = false;
    return 0;
}

int tqueue_register(tqueue_t *tq, unsigned int id, timeout_t *timeout)
{
    if (!tq) {
        return EINVAL;
    }

    if (id < 0 || id > tq->n || !tq->array[id].allocated) {
        ZF_LOGE("invalid id");
        return EINVAL;
    }

    /* delete the callback from the queue if its present */
    if (tq->array[id].active) {
        sglib_tqueue_node_t_delete(&tq->queue, &tq->array[id]);
    }

    /* update node */
    tq->array[id].active = true;
    tq->array[id].timeout = *timeout;

    /* add to data structure */
    sglib_tqueue_node_t_add(&tq->queue, &tq->array[id]);
    return 0;
}

int tqueue_cancel(tqueue_t *tq, unsigned int id) {

    if (!tq) {
        return EINVAL;
    }

    /* iterate through the list until we find that id */
    if (id < 0 || id > tq->n) {
        ZF_LOGE("Invalid id");
        return EINVAL;
    }

    /* delete the callback from the queue if its present */
    if (tq->array[id].active) {
        sglib_tqueue_node_t_delete(&tq->queue, &tq->array[id]);
    }

    tq->array[id].active = false;
    return 0;
}

int tqueue_update(tqueue_t *tq, uint64_t curr_time, uint64_t *next_time) {
    if (!tq) {
        return EINVAL;
    }

    /* keep checking the head of this queue */
    tqueue_node_t *t = head(tq->queue);
    while (t != NULL && t->timeout.abs_time <= curr_time) {
        if (t->active) {
            t->timeout.callback(t->timeout.token);
        }

        /* check if it is active again, as callback may have deactivated the timeout */
        if (t->active) {
            sglib_tqueue_node_t_delete(&tq->queue, t);
            if (t->timeout.period > 0) {
                t->timeout.abs_time += t->timeout.period;
                sglib_tqueue_node_t_add(&tq->queue, t);
            } else {
                t->active = false;
            }
        }
        t = head(tq->queue);
    }

    if (next_time) {
        if (t) {
            *next_time = t->timeout.abs_time;
        } else {
            *next_time = 0;
        }
    }
    return 0;
}

int tqueue_init_static(tqueue_t *tq, ps_malloc_ops_t *mops, int size)
{
    if (!tq || !mops) {
        return EINVAL;
    }

    if (size <= 0) {
        return EINVAL;
    }

    /* initialise the list */
    tq->n = size;
    int error = ps_calloc(mops, size, sizeof(tqueue_node_t), (void **) &tq->array);
    if (error) {
        return ENOMEM;
    }

    assert(tq->array != NULL);

    /* noone currently in the queue */
    tq->queue = NULL;

    return 0;
}
