#include <menu.h>
#include <menu_net.h>
#include <menu_private.h>
#include <game.h>
#include <gui.h>
#include <gui/button.h>
#include <gui/checkbox.h>
#include <gui/container.h>
#include <gui/label.h>
#include <gui/line_edit.h>
#include <errno.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdio.h>
#include <string.h>

struct host_menu
{
    struct gui_container cnt, bcnt;
    struct gui_label error;
    struct menu_net_gui net;
    struct gui_button host, back;
};

static void hide_elements(struct menu_net_gui *const m)
{
    if (m->domain == NET_DOMAIN_IPV4)
    {
        struct menu_ipv4_gui *const g = &m->gui.ipv4;

        g->address.common.hidden = true;
        g->address_le.common.hidden = true;
    }
}

static int update(struct menu_common *const c, void *const arg)
{
    struct host_menu *const m = arg;

    m->bcnt.common.y = screen_h - 40;
    menu_net_gui_update(&m->net);
    m->net.cnt.common.parent = &m->cnt.common;
    hide_elements(&m->net);

    if (gui_update(&m->cnt.common, &c->p, &c->cam, &c->in)
        || gui_update(&m->bcnt.common, &c->p, &c->cam, &c->in))
        return -1;

    return 0;
}

static int render(const struct menu_common *const c, void *const arg)
{
    const struct host_menu *const m = arg;

    if (gui_render(&m->cnt.common)
        || gui_render(&m->bcnt.common))
        return -1;

    return 0;
}

static void init_footer_gui(struct host_menu *const m,
    bool *const back, bool *const host)
{
    {
        struct gui_label *const l = &m->error;

        gui_label_init(l);
        l->font = FONT;
        l->common.hcentered = true;
        l->common.hidden = true;
        gui_add_child(&m->cnt.common, &l->common);
    }

    {
        struct gui_container *const c = &m->bcnt;

        gui_container_init(c);
        c->common.hcentered = true;
        c->mode = GUI_CONTAINER_MODE_H;
    }

    {
        struct gui_button *const b = &m->host;

        gui_button_init(b, GUI_BUTTON_TYPE_1);
        b->u.type1.label.text = "Host";
        b->u.type1.w = 140;
        b->common.vcentered = true;
        b->on_pressed = menu_on_pressed;
        b->arg = host;
        b->common.vcentered = true;
        gui_add_child(&m->bcnt.common, &b->common);
    }

    {
        struct gui_button *const b = &m->back;

        gui_button_init(b, GUI_BUTTON_TYPE_1);
        b->u.type1.label.text = "Back";
        b->u.type1.w = 100;
        b->common.vcentered = true;
        b->on_pressed = menu_on_pressed;
        b->arg = back;
        b->common.vcentered = true;
        gui_add_child(&m->bcnt.common, &b->common);
    }
}

static struct net_host *init_server(const struct host_menu *const m)
{
    union net_server s;

    if (menu_net_server(&m->net, &s))
        return NULL;

    return net_server(&s);
}

int menu_host(struct menu_common *const c)
{
    int ret = -1;
    bool back = false;

    do
    {
        struct host_menu m = {0};
        struct net_host *h = NULL;
        bool host = false;

        gui_container_init(&m.cnt);
        m.cnt.common.hcentered = true;
        m.cnt.common.vcentered = true;
        m.cnt.mode = GUI_CONTAINER_MODE_V;
        m.cnt.spacing = 2;

        menu_net_gui_init(&m.net);
        m.net.cnt.common.hcentered = true;
        gui_add_child(&m.cnt.common, &m.net.cnt.common);

        init_footer_gui(&m, &back, &host);

        while (!back && !c->p.common.exit && !host)
            if (menu_update(c, update, render, &m))
                goto end;

        if (host && (h = init_server(&m)) && menu_gamecfg(c, h, NULL))
            goto end;

        net_close(h);
        gui_deinit(&m.cnt.common, &c->in);
    } while (!back && !c->p.common.exit);

    ret = 0;

end:
    return ret;
}
