#include "waylandinterface_gtk.h"

#include "gtk-ukui-window-management-client-protocol.h"
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

static struct wl_display *s_display = NULL;
static struct wl_registry *s_register = NULL;
static struct ukui_window_management *s_window_management = NULL;
static uint32_t wayland_pid = 0;
static struct ukui_window_management_interface;

static void pid_callback(void *data __attribute__((unused)),
                        struct ukui_window *window __attribute__((unused)),
                        uint32_t pid __attribute__((unused))) {
}

static void geometry_callback(void *data __attribute__((unused)), struct ukui_window *window, int32_t x,
                              int32_t y, uint32_t width, uint32_t height) {
    window_watcher_update_geometry(window, x, y, width, height);
}

static void title_changed_callback(void *data __attribute__((unused)),
                                      struct ukui_window *ukui_window __attribute__((unused)),
                                      const char *title __attribute__((unused))) {}

static void app_id_changed_callback(void *data __attribute__((unused)),
                                       struct ukui_window *ukui_window __attribute__((unused)),
                                       const char *app_id __attribute__((unused))) {}

static void state_changed_callback(void *data __attribute__((unused)), struct ukui_window *ukui_window,
                                   uint32_t flags) {
    int is_active = (flags & 0x1) == 1;
    window_watcher_update_state(ukui_window, is_active);
}

static void themed_icon_name_changed_callback(void *data __attribute__((unused)),
                                                 struct ukui_window *ukui_window __attribute__((unused)),
                                                 const char *name __attribute__((unused))) {}

static void unmapped_callback(void *data __attribute__((unused)), struct ukui_window *ukui_window) {
    window_watcher_remove_window(ukui_window);
}

static void initial_state_callback(void *data __attribute__((unused)),
                                      struct ukui_window *ukui_window __attribute__((unused))) {}

static void parent_window_callback(void *data __attribute__((unused)),
                                      struct ukui_window *ukui_window __attribute__((unused)),
                                      struct ukui_window *parent __attribute__((unused))) {}

static void icon_changed_callback(void *data __attribute__((unused)),
                                   struct ukui_window *ukui_window __attribute__((unused))) {
}

static void virtual_desktop_entered_callback(void *data __attribute__((unused)),
                                                struct ukui_window *ukui_window __attribute__((unused)),
                                                const char *id __attribute__((unused))) {}

static void virtual_desktop_left_callback(void *data __attribute__((unused)),
                                             struct ukui_window *ukui_window __attribute__((unused)),
                                             const char *id __attribute__((unused))) {}

static void application_menu_callback(void *data __attribute__((unused)),
                                         struct ukui_window *ukui_window __attribute__((unused)),
                                         const char *service_name __attribute__((unused)),
                                         const char *object_path __attribute__((unused))) {}

static void activity_entered_callback(void *data __attribute__((unused)),
                                         struct ukui_window *ukui_window __attribute__((unused)),
                                         const char *id __attribute__((unused))) {}

static void activity_left_callback(void *data __attribute__((unused)),
                                      struct ukui_window *ukui_window __attribute__((unused)),
                                      const char *id __attribute__((unused))) {}

static void resource_name_changed_callback(void *data __attribute__((unused)),
                                              struct ukui_window *ukui_window __attribute__((unused)),
                                              const char *resource_name __attribute__((unused))) {}

static const struct ukui_window_listener window_listener = {
    .pid_changed = pid_callback,
    .geometry = geometry_callback,
    .title_changed = title_changed_callback,
    .activity_entered = activity_entered_callback,
    .activity_left = activity_left_callback,
    .app_id_changed = app_id_changed_callback,
    .application_menu = application_menu_callback,
    .icon_changed = icon_changed_callback,
    .initial_state = initial_state_callback,
    .parent_window = parent_window_callback,
    .resource_name_changed = resource_name_changed_callback,
    .state_changed = state_changed_callback,
    .themed_icon_name_changed = themed_icon_name_changed_callback,
    .unmapped = unmapped_callback,
    .virtual_desktop_entered = virtual_desktop_entered_callback,
    .virtual_desktop_left = virtual_desktop_left_callback,
};

static void show_desktop_changed_callback(
    void *data __attribute__((unused)),
    struct ukui_window_management *ukui_window_management __attribute__((unused)),
    uint32_t state __attribute__((unused))) {}

static void stacking_order_change_callback(
    void *data __attribute__((unused)),
    struct ukui_window_management *ukui_window_management __attribute__((unused)),
    const char *uuids __attribute__((unused))) {}

static void
window_create_callback(void *data __attribute__((unused)),
                       struct ukui_window_management *ukui_window_management,
                       const char *uuid) {
    struct ukui_window *window =
        ukui_window_management_create_window(ukui_window_management, uuid);
    if (window == NULL) {
        return;
    }
    ukui_window_add_listener(window, &window_listener, (void *)uuid);
    window_watcher_add_window(uuid, window);
}

static const struct ukui_window_management_listener wm_lisener = {
    .window_created = window_create_callback,
    .show_desktop_changed = show_desktop_changed_callback,
    .stacking_order_changed = stacking_order_change_callback};

static void handle_global(void *data, struct wl_registry *registry,
                          uint32_t name, const char *interface,
                          uint32_t version) {
    void *expected_instance = window_watcher_get_instance();
    if (data != expected_instance) {
        return;
    }

    if (strcmp(interface, ukui_window_management_interface.name) == 0) {
        s_window_management = (struct ukui_window_management *)wl_registry_bind(
            registry, name, &ukui_window_management_interface, version);
        if (s_window_management) {
            ukui_window_management_add_listener(s_window_management,
                                                &wm_lisener, data);
        }
    }
}

static void handle_global_remove(void *data __attribute__((unused)),
                                    struct wl_registry *wl_registry __attribute__((unused)),
                                    uint32_t name __attribute__((unused))) {}

static const struct wl_registry_listener registry_listener = {
    .global = handle_global, .global_remove = handle_global_remove};

void initWindow(struct wl_display *display) {
    s_register = wl_display_get_registry(display);
    void *window_watcher_instance = window_watcher_get_instance();
    wl_registry_add_listener(s_register, &registry_listener,
                             window_watcher_instance);
    wl_display_roundtrip(display);
}
