#include <gui/container.h>
#include <gui.h>
#include <camera.h>
#include <input.h>
#include <peripheral.h>

static void add_child(struct gui_common *const parent,
    struct gui_common *const child)
{
    if (child->hidden || !child->cb || !child->cb->get_dim)
        return;

    struct gui_container *const c = (struct gui_container *)parent;
    short w, h;

    child->cb->get_dim(child, &w, &h);

    switch (c->mode)
    {
        case GUI_CONTAINER_MODE_H:
            if (c->w)
                c->w += c->spacing;

            child->xoff = c->w;
            c->w += w;

            if (h > c->h)
                c->h = h;

            break;

        case GUI_CONTAINER_MODE_V:
            if (c->h)
                c->h += c->spacing;

            child->yoff = c->h;
            c->h += h;

            if (w > c->w)
                c->w = w;

            break;
    }
}

static void get_dim(const struct gui_common *const g,
    short *const w, short *const h)
{
    struct gui_container *const c = (struct gui_container *)g;

    *w = c->w;
    *h = c->h;
}

static int update(struct gui_common *const g,
    const union peripheral *const p, const struct camera *const cam,
    struct input *const in)
{
    struct gui_container *const c = (struct gui_container *)g;

    c->w = c->h = 0;

    struct gui_common *const child = c->common.child;

    if (child && child->cb)
    {
        if (child->cb->get_dim)
            add_child(&c->common, child);

        for (struct gui_common *s = child->sibling; s; s = s->sibling)
            add_child(&c->common, s);
    }

    return 0;
}

void gui_container_init(struct gui_container *const c)
{
    static const struct gui_common_cb cb =
    {
        .add_child = add_child,
        .get_dim = get_dim,
        .update = update
    };

    *c = (const struct gui_container)
    {
        .common =
        {
            .cb = &cb
        }
    };
}
