#include "eekboard/eekboard-context-service.h"
#include "wayland.h"
#include "panel.h"


// Called from rust
/// Destroys the widget
void
panel_manager_hide(struct panel_manager *self)
{
    if (self->window) {
        gtk_widget_hide (GTK_WIDGET (self->window));
    }
}

static void
on_destroy (struct panel_manager *self, GtkWidget *widget)
{
    g_assert (widget == GTK_WIDGET(self->window));
    panel_manager_hide(self);
}


/// panel::Manager. Only needed for this callback
struct squeek_panel_manager;

/// Calls back into Rust
void squeek_panel_manager_configured(struct squeek_panel_manager *mgr, uint32_t width, uint32_t height);

static void
on_surface_configure(struct squeek_panel_manager *self, PhoshLayerSurface *surface)
{
    gint width;
    gint height;
    g_return_if_fail (PHOSH_IS_LAYER_SURFACE (surface));

    g_object_get(G_OBJECT(surface),
                 "configured-width", &width,
                 "configured-height", &height,
                 NULL);
    squeek_panel_manager_configured(self, width, height);
}

static void
make_widget (struct panel_manager *self)
{
    if (self->widget) {
        g_error("Widget already present");
    }
    self->widget = eek_gtk_keyboard_new (self->state, self->submission, self->state_manager, self->popover);

    gtk_widget_set_has_tooltip (self->widget, TRUE);
    gtk_container_add (GTK_CONTAINER(self->window), self->widget);
    gtk_widget_show_all(self->widget);
}


// Called also from rust
/// Updates the size
void
panel_manager_resize (struct panel_manager *self, uint32_t height)
{
    phosh_layer_surface_set_size(self->window, 0, height);
    phosh_layer_surface_set_exclusive_zone(self->window, height);
    phosh_layer_surface_wl_surface_commit(self->window);
}

// Called from rust
/// Creates a new panel widget
void
panel_manager_request_widget (struct panel_manager *self, struct wl_output *output, uint32_t height, struct squeek_panel_manager *mgr)
{
    if (!self->window) {
        self->window = g_object_new (
            PHOSH_TYPE_LAYER_SURFACE,
            "layer-shell", squeek_wayland->layer_shell,
            "wl-output", output,
            "height", height,
            "anchor", ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM
            | ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT
            | ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT,
            "layer", ZWLR_LAYER_SHELL_V1_LAYER_TOP,
            "kbd-interactivity", FALSE,
            "exclusive-zone", height,
            "namespace", "osk",
            NULL
        );
        g_object_connect (self->window,
            "swapped-signal::destroy", G_CALLBACK(on_destroy), self,
            "swapped-signal::configured", G_CALLBACK(on_surface_configure), mgr,
            NULL);
        // The properties below are just to make hacking easier.
        // The way we use layer-shell overrides some,
        // and there's no space in the protocol for others.
        // Those may still be useful in the future,
        // or for hacks with regular windows.
        gtk_widget_set_can_focus (GTK_WIDGET(self->window), FALSE);
        g_object_set (G_OBJECT(self->window), "accept_focus", FALSE, NULL);
        gtk_window_set_title (GTK_WINDOW(self->window), "Squeekboard");
        gtk_window_set_icon_name (GTK_WINDOW(self->window), "squeekboard");
        gtk_window_set_keep_above (GTK_WINDOW(self->window), TRUE);
    } else {
        panel_manager_resize(self, height);
    }

    if (!self->widget) {
        make_widget(self);
    }

    gtk_widget_show (GTK_WIDGET(self->window));
}

struct panel_manager panel_manager_new(EekboardContextService *state, struct submission *submission, struct squeek_state_manager *state_manager, struct squeek_popover *popover)
{
    struct panel_manager mgr = {
        .state = state,
        .submission = submission,
        .window = NULL,
        .widget = NULL,
        .current_output = NULL,
        .state_manager = state_manager,
        .popover = popover,
    };
    return mgr;
}
