#include <peripheral.h>
#include <gfx.h>
#include <keyboard.h>
#include <mouse.h>
#include <pad.h>

static void update_pad_common(union peripheral *const p)
{
    if (pad_justpressed(&p->pad.pad, PAD_KEY_EXIT))
        p->common.exit = true;
}

static void update_kbm_common(union peripheral *const p)
{
    struct peripheral_kbm *const kbm = &p->kbm;
    struct keyboard *const k = &kbm->keyboard;

    if (keyboard_justpressed(k, &KEYBOARD_COMBO(KEYBOARD_KEY_EXIT)))
        p->common.exit = true;
    else if (keyboard_justreleased(k, &KEYBOARD_COMBO(KEYBOARD_KEY_F11)))
        gfx_toggle_fullscreen();
}

void peripheral_update(union peripheral *const p)
{
    switch (p->common.type)
    {
        case PERIPHERAL_TYPE_TOUCH:
            /* Fall through. */
        case PERIPHERAL_TYPE_KEYBOARD_MOUSE:
            mouse_update(&p->kbm.mouse);
            keyboard_update(&p->kbm.keyboard);
            update_kbm_common(p);
            break;

        case PERIPHERAL_TYPE_PAD:
            pad_update(&p->pad.pad);
            update_pad_common(p);
            break;
    }
}

void peripheral_init(const struct peripheral_cfg *const cfg,
    union peripheral *const p)
{
    p->common = (const struct peripheral_common){0};

    switch (p->common.type = cfg->type)
    {
        case PERIPHERAL_TYPE_TOUCH:
            /* Fall through. */
        case PERIPHERAL_TYPE_KEYBOARD_MOUSE:
            mouse_init(&p->kbm.mouse);
            keyboard_init(&p->kbm.keyboard);
            break;

        case PERIPHERAL_TYPE_PAD:
            pad_init(cfg->padn, &p->pad.pad);
            break;
    }
}

int peripheral_get_default(struct peripheral_cfg *const cfg)
{
    *cfg = (const struct peripheral_cfg){0};

    if (pad_count())
        cfg->type = PERIPHERAL_TYPE_PAD;
    else if (keyboard_available() && mouse_available())
        cfg->type = PERIPHERAL_TYPE_KEYBOARD_MOUSE;
    else
        return -1;

    return 0;
}
