/*
 * Copyright (C) 2012 Igalia S.L.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 * THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "config.h"
#include "PlatformWebView.h"

#include <WebCore/GUniquePtrGtk.h>
#include <WebCore/GtkVersioning.h>
#include <WebKit/WKRetainPtr.h>
#include <WebKit/WKView.h>
#include <gtk/gtk.h>
#include <wtf/glib/GUniquePtr.h>

namespace TestWebKitAPI {

PlatformWebView::PlatformWebView(WKContextRef contextRef, WKPageGroupRef pageGroupRef)
{
    WKRetainPtr<WKPageConfigurationRef> configuration = adoptWK(WKPageConfigurationCreate());
    WKPageConfigurationSetContext(configuration.get(), contextRef);
    WKPageConfigurationSetPageGroup(configuration.get(), pageGroupRef);

    initialize(configuration.get());
}

PlatformWebView::PlatformWebView(WKPageConfigurationRef configuration)
{
    initialize(configuration);
}

PlatformWebView::PlatformWebView(WKPageRef relatedPage)
{
    WKRetainPtr<WKPageConfigurationRef> configuration = adoptWK(WKPageConfigurationCreate());
    WKPageConfigurationSetContext(configuration.get(), WKPageGetContext(relatedPage));
    WKPageConfigurationSetPageGroup(configuration.get(), WKPageGetPageGroup(relatedPage));
    WKPageConfigurationSetRelatedPage(configuration.get(), relatedPage);

    initialize(configuration.get());
}

PlatformWebView::~PlatformWebView()
{
    gtk_widget_destroy(m_window);
}

void PlatformWebView::initialize(WKPageConfigurationRef configuration)
{
    m_window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
    m_view = WKViewCreate(configuration);
    gtk_container_add(GTK_CONTAINER(m_window), GTK_WIDGET(m_view));
    gtk_widget_show(GTK_WIDGET(m_view));
    gtk_widget_show(m_window);
}

WKPageRef PlatformWebView::page() const
{
    return WKViewGetPage(m_view);
}

void PlatformWebView::resizeTo(unsigned width, unsigned height)
{
    gtk_window_resize(GTK_WINDOW(m_window), width, height);
}

static void doKeyStroke(GtkWidget* viewWidget, unsigned int keyVal)
{
    GUniquePtr<GdkEvent> event(gdk_event_new(GDK_KEY_PRESS));
    event->key.keyval = keyVal;
    event->key.time = GDK_CURRENT_TIME;
    event->key.state = 0;
    event->key.window = gtk_widget_get_window(viewWidget);
    g_object_ref(event->key.window);
    GdkDisplay* display = gtk_widget_get_display(viewWidget);
    gdk_event_set_device(event.get(), gdk_seat_get_pointer(gdk_display_get_default_seat(display)));

    // When synthesizing an event, an invalid hardware_keycode value can cause it to be badly processed by GTK+.
    GUniqueOutPtr<GdkKeymapKey> keys;
    int keysCount;
    if (gdk_keymap_get_entries_for_keyval(gdk_keymap_get_for_display(display), keyVal, &keys.outPtr(), &keysCount) && keysCount)
        event->key.hardware_keycode = keys.get()[0].keycode;

    gtk_main_do_event(event.get());
    event->key.type = GDK_KEY_RELEASE;
    gtk_main_do_event(event.get());
}

void PlatformWebView::simulateSpacebarKeyPress()
{
    GtkWidget* viewWidget = GTK_WIDGET(m_view);
    if (!gtk_widget_get_realized(viewWidget))
        gtk_widget_show(m_window);
    doKeyStroke(viewWidget, GDK_KEY_KP_Space);
}

void PlatformWebView::simulateAltKeyPress()
{
    GtkWidget* viewWidget = GTK_WIDGET(m_view);
    if (!gtk_widget_get_realized(viewWidget))
        gtk_widget_show(m_window);
    doKeyStroke(viewWidget, GDK_KEY_Alt_L);
}

static void doMouseButtonEvent(GtkWidget* viewWidget, GdkEventType eventType, int x, int y, unsigned int button)
{
    GUniquePtr<GdkEvent> event(gdk_event_new(eventType));
    event->button.x = x;
    event->button.y = y;
    event->button.button = button;
    event->button.time = GDK_CURRENT_TIME;
    event->button.axes = 0;
    event->button.state = 0;
    event->button.window = gtk_widget_get_window(viewWidget);
    g_object_ref(event->button.window);
    event->button.device = gdk_seat_get_pointer(gdk_display_get_default_seat(gtk_widget_get_display(viewWidget)));

    int xRoot, yRoot;
    gdk_window_get_root_coords(gtk_widget_get_window(viewWidget), x, y, &xRoot, &yRoot);
    event->button.x_root = xRoot;
    event->button.y_root = yRoot;
    gtk_main_do_event(event.get());
}

void PlatformWebView::simulateRightClick(unsigned x, unsigned y)
{
    GtkWidget* viewWidget = GTK_WIDGET(m_view);
    if (!gtk_widget_get_realized(viewWidget))
        gtk_widget_show(m_window);
    doMouseButtonEvent(viewWidget, GDK_BUTTON_PRESS, x, y, 3);
    doMouseButtonEvent(viewWidget, GDK_BUTTON_RELEASE, x, y, 3);
}

void PlatformWebView::simulateMouseMove(unsigned x, unsigned y, WKEventModifiers)
{
    GUniquePtr<GdkEvent> event(gdk_event_new(GDK_MOTION_NOTIFY));
    event->motion.x = x;
    event->motion.y = y;
    event->motion.time = GDK_CURRENT_TIME;
    event->motion.state = 0;
    event->motion.axes = 0;

    GtkWidget* viewWidget = GTK_WIDGET(m_view);
    if (!gtk_widget_get_realized(viewWidget))
        gtk_widget_show(m_window);
    event->motion.window = gtk_widget_get_window(viewWidget);
    g_object_ref(event->motion.window);
    event->motion.device = gdk_seat_get_pointer(gdk_display_get_default_seat(gtk_widget_get_display(viewWidget)));

    int xRoot, yRoot;
    gdk_window_get_root_coords(gtk_widget_get_window(viewWidget), x, y, &xRoot, &yRoot);
    event->motion.x_root = xRoot;
    event->motion.y_root = yRoot;
    gtk_main_do_event(event.get());
}

} // namespace TestWebKitAPI
