#include "session_private.h"
#include "session_timer.h"

struct session_timer
{
    struct timeouts *timeouts;
};

struct session_timer *session_timer_new(uint64_t now)
{
    timeout_error_t err;
    struct session_timer *timer = (struct session_timer *)calloc(1, sizeof(struct session_timer));
    if (timer == NULL)
    {
        return NULL;
    }

    timer->timeouts = timeouts_open(0, &err);
    if (timer->timeouts == NULL)
    {
        goto error;
    }
    timeouts_update(timer->timeouts, now);

    return timer;

error:
    session_timer_free(timer);
    return NULL;
}

void session_timer_free(struct session_timer *timer)
{
    if (timer)
    {
        if (timer->timeouts)
        {
            timeouts_close(timer->timeouts);
        }

        free(timer);
        timer = NULL;
    }
}

void session_timer_add(struct session_timer *timer, struct session *sess, uint64_t expires)
{
    timeout_init(&sess->timeout, TIMEOUT_ABS);
    timeouts_add(timer->timeouts, &sess->timeout, expires);
}

void session_timer_del(struct session_timer *timer, struct session *sess)
{
    timeouts_del(timer->timeouts, &sess->timeout);
}

void session_timer_update(struct session_timer *timer, struct session *sess, uint64_t expires)
{
    session_timer_del(timer, sess);
    session_timer_add(timer, sess, expires);
}

struct session *session_timer_expire(struct session_timer *timer, uint64_t now)
{
    timeouts_update(timer->timeouts, now);

    struct timeout *timeout = timeouts_get(timer->timeouts);
    if (timeout == NULL)
    {
        return NULL;
    }

    return container_of(timeout, struct session, timeout);
}

uint64_t session_timer_next_expire_interval(struct session_timer *timer)
{
    return timeouts_timeout(timer->timeouts);
}