/*
 * Copyright (C) 2020 Igalia S.L.
 * All rights reserved.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public License
 * along with this library; see the file COPYING.LIB.  If not, write to
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301, USA.
 */

#pragma once

#include <gtk/gtk.h>

#if USE(GTK4)

#define GDK_MOD1_MASK GDK_ALT_MASK

typedef GdkKeyEvent GdkEventKey;
typedef GdkFocusEvent GdkEventFocus;

static inline gboolean
gtk_widget_is_toplevel(GtkWidget* widget)
{
    // In theory anything which implements GtkRoot can be a toplevel widget,
    // in practice only the ones which are GtkWindow or derived need to be
    // considered here.
    return GTK_IS_WINDOW(widget);
}

static inline GtkWidget*
gtk_widget_get_toplevel(GtkWidget* widget)
{
    return GTK_WIDGET(gtk_widget_get_root(widget));
}

static inline void
gtk_widget_destroy(GtkWidget* widget)
{
    ASSERT(GTK_IS_WINDOW(widget));
    gtk_window_destroy(GTK_WINDOW(widget));
}

static inline void
gtk_window_get_position(GtkWindow*, int* x, int* y)
{
    *x = *y = 0;
}

static inline void
gtk_window_move(GtkWindow*, int, int)
{
}

static inline void
gtk_window_resize(GtkWindow* window, int width, int height)
{
    gtk_window_set_default_size(window, width, height);
}

static inline void
gtk_window_get_size(GtkWindow* window, int* width, int* height)
{
    gtk_window_get_default_size(window, width, height);
}

static inline void
gtk_init(int*, char***)
{
    gtk_init();
}

static inline gboolean
gtk_init_check(int*, char***)
{
    return gtk_init_check();
}

static inline GdkEvent*
gdk_event_copy(GdkEvent* event)
{
    return gdk_event_ref(event);
}

static inline GdkDevice*
gdk_event_get_source_device(const GdkEvent* event)
{
    return gdk_event_get_device(const_cast<GdkEvent*>(event));
}

static inline void
gtk_widget_size_allocate(GtkWidget* widget, GtkAllocation* allocation)
{
    gtk_widget_size_allocate(widget, allocation, -1);
}

static inline void
gtk_widget_queue_resize_no_redraw(GtkWidget* widget)
{
    gtk_widget_queue_resize(widget);
}

static inline void
gtk_entry_set_text(GtkEntry* entry, const char* text)
{
    gtk_editable_set_text(GTK_EDITABLE(entry), text);
}

static inline const char*
gtk_entry_get_text(GtkEntry* entry)
{
    return gtk_editable_get_text(GTK_EDITABLE(entry));
}

static inline void
gtk_label_set_line_wrap(GtkLabel* label, gboolean enable)
{
    gtk_label_set_wrap(label, enable);
}

static inline void
gtk_window_set_default(GtkWindow* window, GtkWidget* widget)
{
    gtk_window_set_default_widget(window, widget);
}

static inline gboolean
gdk_event_get_state(const GdkEvent *event, GdkModifierType *state)
{
    *state = gdk_event_get_modifier_state(const_cast<GdkEvent*>(event));
    // The GTK3 method returns TRUE if there is a state, otherwise
    // FALSE.
    return !!*state;
}

static inline gboolean
gdk_event_get_coords(const GdkEvent *event, double *x, double *y)
{
    return gdk_event_get_position(const_cast<GdkEvent*>(event), x, y);
}

static inline gboolean
gdk_event_get_root_coords(const GdkEvent *event, double *x, double *y)
{
    // GTK4 does not provide a way of obtaining screen-relative event coordinates, and even
    // on Wayland GTK3 cannot know where a surface is and will return the surface-relative
    // coordinates anyway, so do the same here.
    return gdk_event_get_position(const_cast<GdkEvent*>(event), x, y);
}

static inline gboolean
gdk_event_is_scroll_stop_event(const GdkEvent* event)
{
    return gdk_scroll_event_is_stop(const_cast<GdkEvent*>(event));
}

static inline gboolean
gdk_event_get_scroll_direction(const GdkEvent* event, GdkScrollDirection* direction)
{
    *direction = gdk_scroll_event_get_direction(const_cast<GdkEvent*>(event));
    // The GTK3 method returns TRUE if the scroll direction is not
    // GDK_SCROLL_SMOOTH, so do the same here.
    return *direction != GDK_SCROLL_SMOOTH;
}

static inline gboolean
gdk_event_get_scroll_deltas(const GdkEvent* event, gdouble *x, gdouble *y)
{
    gdk_scroll_event_get_deltas(const_cast<GdkEvent*>(event), x, y);
    // The GTK3 method returns TRUE if the event is a smooth scroll
    // event, so do the same here.
    return gdk_scroll_event_get_direction(const_cast<GdkEvent*>(event)) == GDK_SCROLL_SMOOTH;
}

static inline gboolean
gdk_event_get_button(const GdkEvent* event, guint* button)
{
    if (button)
        *button = gdk_button_event_get_button(const_cast<GdkEvent*>(event));
    return true;
}

static inline gboolean
gdk_event_get_keyval(const GdkEvent* event, guint* keyval)
{
    if (keyval)
        *keyval = gdk_key_event_get_keyval(const_cast<GdkEvent*>(event));
    return TRUE;
}

static inline gboolean
gdk_event_get_keycode(const GdkEvent* event, guint16* keycode)
{
    if (keycode)
        *keycode = gdk_key_event_get_keycode(const_cast<GdkEvent*>(event));
    return TRUE;
}

static inline int
gtk_native_dialog_run(GtkNativeDialog* dialog)
{
    struct RunDialogContext {
        GMainLoop *loop;
        int response;
    } context = { g_main_loop_new(nullptr, FALSE), 0 };

    gtk_native_dialog_show(dialog);
    g_signal_connect(dialog, "response", G_CALLBACK(+[](GtkNativeDialog*, int response, RunDialogContext* context) {
        context->response = response;
        g_main_loop_quit(context->loop);
    }), &context);
    g_main_loop_run(context.loop);
    g_main_loop_unref(context.loop);

    return context.response;
}

static inline int
gtk_dialog_run(GtkDialog* dialog)
{
    struct RunDialogContext {
        GMainLoop *loop;
        int response;
    } context = { g_main_loop_new(nullptr, FALSE), 0 };

    gtk_widget_show(GTK_WIDGET(dialog));
    g_signal_connect(dialog, "response", G_CALLBACK(+[](GtkDialog*, int response, RunDialogContext* context) {
        context->response = response;
        g_main_loop_quit(context->loop);
    }), &context);
    g_main_loop_run(context.loop);
    g_main_loop_unref(context.loop);

    return context.response;
}

static inline void
gtk_tree_view_column_cell_get_size(GtkTreeViewColumn* column, const GdkRectangle*, gint* xOffset, gint* yOffset, gint* width, gint* height)
{
    gtk_tree_view_column_cell_get_size(column, xOffset, yOffset, width, height);
}

#else // USE(GTK4)

static inline void
gtk_widget_add_css_class(GtkWidget* widget, const char* name)
{
    gtk_style_context_add_class(gtk_widget_get_style_context(widget), name);
}

static inline void
gtk_window_minimize(GtkWindow* window)
{
    gtk_window_iconify(window);
}

static inline void
gtk_window_unminimize(GtkWindow* window)
{
    gtk_window_deiconify(window);
}

static inline GtkWidget*
gtk_scrolled_window_new()
{
    return gtk_scrolled_window_new(nullptr, nullptr);
}

static inline GdkModifierType
gtk_event_controller_get_current_event_state(GtkEventController*)
{
    GdkModifierType modifiers;
    gtk_get_current_event_state(&modifiers);
    return modifiers;
}

static inline uint32_t
gtk_event_controller_get_current_event_time(GtkEventController*)
{
    return gtk_get_current_event_time();
}

#endif // USE(GTK4)
