#include "tinylib.h"

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

struct tiny_handle {
    char     name[64];
    long     total;
    tiny_cb  cb;
    void    *userdata;
};

int
tiny_open(const char *name, tiny_handle **out)
{
    if (name == NULL || out == NULL || name[0] == '\0') {
        return TINY_EINVAL;
    }
    size_t len = strlen(name);
    if (len >= sizeof(((struct tiny_handle *)0)->name)) {
        return TINY_ERANGE;
    }
    struct tiny_handle *h = calloc(1, sizeof(*h));
    if (h == NULL) {
        return TINY_ENOMEM;
    }
    memcpy(h->name, name, len + 1);
    *out = h;
    return TINY_OK;
}

void
tiny_close(tiny_handle *h)
{
    free(h);
}

int
tiny_push(tiny_handle *h, int value)
{
    if (h == NULL) {
        return TINY_EINVAL;
    }
    if (value < -1000 || value > 1000) {
        return TINY_ERANGE;
    }
    h->total += value;
    if (h->cb != NULL) {
        h->cb(h->userdata, value);
    }
    return TINY_OK;
}

int
tiny_total(tiny_handle *h, long *out)
{
    if (h == NULL || out == NULL) {
        return TINY_EINVAL;
    }
    *out = h->total;
    return TINY_OK;
}

void
tiny_set_callback(tiny_handle *h, tiny_cb cb, void *userdata)
{
    if (h != NULL) {
        h->cb = cb;
        h->userdata = userdata;
    }
}

const char *
tiny_strerror(int rc)
{
    switch (rc) {
    case TINY_OK:     return "ok";
    case TINY_EINVAL: return "invalid argument";
    case TINY_ENOMEM: return "out of memory";
    case TINY_ERANGE: return "value out of range";
    default:          return "unknown error";
    }
}
