/*
 * Copyright (C) 2012 Igalia S.L.
 *
 * 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.
 */

#include "config.h"

#include "WebViewTest.h"
#include <wtf/Vector.h>
#include <wtf/glib/GRefPtr.h>

class InspectorTest: public WebViewTest {
public:
    MAKE_GLIB_TEST_FIXTURE(InspectorTest);

    enum InspectorEvents {
        OpenWindow,
        BringToFront,
        Closed,
        Attach,
        Detach
    };

    static gboolean openWindowCallback(WebKitWebInspector*, InspectorTest* test)
    {
        return test->openWindow();
    }

    static gboolean bringToFrontCallback(WebKitWebInspector*, InspectorTest* test)
    {
        return test->bringToFront();
    }

    static void closedCallback(WebKitWebInspector*, InspectorTest* test)
    {
        return test->closed();
    }

    static gboolean attachCallback(WebKitWebInspector*, InspectorTest* test)
    {
        return test->attach();
    }

    static gboolean detachCallback(WebKitWebInspector*, InspectorTest* test)
    {
        return test->detach();
    }

    static const unsigned gMinimumAttachedInspectorWidth = 750;
    static const unsigned gMinimumAttachedInspectorHeight = 250;

    InspectorTest()
        : WebViewTest()
        , m_inspector(webkit_web_view_get_inspector(m_webView))
    {
        webkit_settings_set_enable_developer_extras(webkit_web_view_get_settings(m_webView), TRUE);
        assertObjectIsDeletedWhenTestFinishes(G_OBJECT(m_inspector));
        g_signal_connect(m_inspector, "open-window", G_CALLBACK(openWindowCallback), this);
        g_signal_connect(m_inspector, "bring-to-front", G_CALLBACK(bringToFrontCallback), this);
        g_signal_connect(m_inspector, "closed", G_CALLBACK(closedCallback), this);
        g_signal_connect(m_inspector, "attach", G_CALLBACK(attachCallback), this);
        g_signal_connect(m_inspector, "detach", G_CALLBACK(detachCallback), this);
    }

    ~InspectorTest()
    {
        g_signal_handlers_disconnect_matched(m_inspector, G_SIGNAL_MATCH_DATA, 0, 0, 0, 0, this);
    }

    virtual bool openWindow()
    {
        m_events.append(OpenWindow);
        g_main_loop_quit(m_mainLoop);
        return TRUE;
    }

    virtual bool bringToFront()
    {
        m_events.append(BringToFront);
        g_main_loop_quit(m_mainLoop);
        return FALSE;
    }

    virtual void closed()
    {
        m_events.append(Closed);
    }

    virtual bool attach()
    {
        m_events.append(Attach);
        return TRUE;
    }

    virtual bool detach()
    {
        m_events.append(Detach);
        return TRUE;
    }


    static gboolean showIdle(InspectorTest* test)
    {
        webkit_web_inspector_show(test->m_inspector);
        return FALSE;
    }

    void show()
    {
        g_idle_add(reinterpret_cast<GSourceFunc>(showIdle), this);
        g_main_loop_run(m_mainLoop);
    }

    static void canAttachChanged(InspectorTest* test)
    {
        g_main_loop_quit(test->m_mainLoop);
    }

    void resizeViewAndAttach()
    {
        // Resize the view to make room for the inspector.
        if (!webkit_web_inspector_get_can_attach(m_inspector)) {
            unsigned long handler = g_signal_connect_swapped(m_inspector, "notify::can-attach", G_CALLBACK(canAttachChanged), this);
            resizeView(gMinimumAttachedInspectorWidth, (gMinimumAttachedInspectorHeight + 1) * 4 / 3);
            g_main_loop_run(m_mainLoop);
            g_signal_handler_disconnect(m_inspector, handler);
        }

        g_assert_true(webkit_web_inspector_get_can_attach(m_inspector));
        webkit_web_inspector_attach(m_inspector);
    }

    static gboolean detachIdle(InspectorTest* test)
    {
        webkit_web_inspector_detach(test->m_inspector);
        return FALSE;
    }

    void detachAndWaitUntilWindowOpened()
    {
        g_idle_add(reinterpret_cast<GSourceFunc>(detachIdle), this);
        g_main_loop_run(m_mainLoop);
    }

    void close()
    {
        webkit_web_inspector_close(m_inspector);
    }

    WebKitWebInspector* m_inspector;
    Vector<InspectorEvents> m_events;
};

static void testInspectorDefault(InspectorTest* test, gconstpointer)
{
    test->showInWindowAndWaitUntilMapped(GTK_WINDOW_TOPLEVEL);
    test->resizeView(200, 200);
    test->loadHtml("<html><body><p>WebKitGTK Inspector test</p></body></html>", 0);
    test->waitUntilLoadFinished();

    test->show();
    // We don't add the view to a container, so consume the weak ref with GRefPtr.
    GRefPtr<WebKitWebViewBase> inspectorView = webkit_web_inspector_get_web_view(test->m_inspector);
    g_assert_nonnull(inspectorView.get());
    test->assertObjectIsDeletedWhenTestFinishes(G_OBJECT(inspectorView.get()));
    g_assert_false(webkit_web_inspector_is_attached(test->m_inspector));
    g_assert_cmpuint(webkit_web_inspector_get_attached_height(test->m_inspector), ==, 0);
    g_assert_false(webkit_web_inspector_get_can_attach(test->m_inspector));
    Vector<InspectorTest::InspectorEvents>& events = test->m_events;
    g_assert_cmpint(events.size(), ==, 1);
    g_assert_cmpint(events[0], ==, InspectorTest::OpenWindow);
    test->m_events.clear();

    test->show();
    events = test->m_events;
    g_assert_cmpint(events.size(), ==, 1);
    g_assert_cmpint(events[0], ==, InspectorTest::BringToFront);
    test->m_events.clear();

    test->resizeViewAndAttach();
    g_assert_true(webkit_web_inspector_is_attached(test->m_inspector));
    g_assert_cmpuint(webkit_web_inspector_get_attached_height(test->m_inspector), >=, InspectorTest::gMinimumAttachedInspectorHeight);
    events = test->m_events;
    g_assert_cmpint(events.size(), ==, 1);
    g_assert_cmpint(events[0], ==, InspectorTest::Attach);
    test->m_events.clear();

    test->detachAndWaitUntilWindowOpened();
    g_assert_false(webkit_web_inspector_is_attached(test->m_inspector));
    events = test->m_events;
    g_assert_cmpint(events.size(), ==, 2);
    g_assert_cmpint(events[0], ==, InspectorTest::Detach);
    g_assert_cmpint(events[1], ==, InspectorTest::OpenWindow);
    test->m_events.clear();

    test->close();
    events = test->m_events;
    g_assert_cmpint(events.size(), ==, 1);
    g_assert_cmpint(events[0], ==, InspectorTest::Closed);
    test->m_events.clear();
}

class CustomInspectorTest: public InspectorTest {
public:
    MAKE_GLIB_TEST_FIXTURE(CustomInspectorTest);

    CustomInspectorTest()
        : InspectorTest()
        , m_inspectorWindow(0)
    {
    }

    ~CustomInspectorTest()
    {
        if (m_inspectorWindow)
            gtk_widget_destroy(m_inspectorWindow);
    }

    bool openWindow()
    {
        g_assert_null(m_inspectorWindow);
        m_inspectorWindow = gtk_window_new(GTK_WINDOW_TOPLEVEL);
        WebKitWebViewBase* inspectorView = webkit_web_inspector_get_web_view(m_inspector);
        g_assert_nonnull(inspectorView);
        gtk_container_add(GTK_CONTAINER(m_inspectorWindow), GTK_WIDGET(inspectorView));
        gtk_widget_show_all(m_inspectorWindow);

        return InspectorTest::openWindow();
    }

    void closed()
    {
        if (m_inspectorWindow) {
            gtk_widget_destroy(m_inspectorWindow);
            m_inspectorWindow = 0;
        }

        return InspectorTest::closed();
    }

    bool attach()
    {
        GRefPtr<WebKitWebViewBase> inspectorView = webkit_web_inspector_get_web_view(m_inspector);
        if (m_inspectorWindow) {
            gtk_container_remove(GTK_CONTAINER(m_inspectorWindow), GTK_WIDGET(inspectorView.get()));
            gtk_widget_destroy(m_inspectorWindow);
            m_inspectorWindow = 0;
        }

        GtkWidget* pane;
        if (gtk_bin_get_child(GTK_BIN(m_parentWindow)) == GTK_WIDGET(m_webView)) {
            GRefPtr<WebKitWebView> inspectedView = m_webView;
            gtk_container_remove(GTK_CONTAINER(m_parentWindow), GTK_WIDGET(m_webView));
            pane = gtk_paned_new(GTK_ORIENTATION_VERTICAL);
            gtk_paned_add1(GTK_PANED(pane), GTK_WIDGET(m_webView));
            gtk_container_add(GTK_CONTAINER(m_parentWindow), pane);
            gtk_widget_show_all(pane);
        } else
            pane = gtk_bin_get_child(GTK_BIN(m_parentWindow));
        gtk_paned_set_position(GTK_PANED(pane), webkit_web_inspector_get_attached_height(m_inspector));
        gtk_paned_add2(GTK_PANED(pane), GTK_WIDGET(inspectorView.get()));

        return InspectorTest::attach();
    }

    bool detach()
    {
        GRefPtr<WebKitWebViewBase> inspectorView = webkit_web_inspector_get_web_view(m_inspector);
        GtkWidget* pane = gtk_bin_get_child(GTK_BIN(m_parentWindow));
        g_assert_true(GTK_IS_PANED(pane));
        gtk_container_remove(GTK_CONTAINER(pane), GTK_WIDGET(inspectorView.get()));
        return InspectorTest::detach();
    }

    void destroyWindow()
    {
        g_assert_nonnull(m_inspectorWindow);
        gtk_widget_destroy(m_inspectorWindow);
        m_inspectorWindow = 0;
    }

    GtkWidget* m_inspectorWindow;
};

static void testInspectorManualAttachDetach(CustomInspectorTest* test, gconstpointer)
{
    test->showInWindowAndWaitUntilMapped(GTK_WINDOW_TOPLEVEL);
    test->resizeView(200, 200);
    test->loadHtml("<html><body><p>WebKitGTK Inspector test</p></body></html>", 0);
    test->waitUntilLoadFinished();

    test->show();
    test->assertObjectIsDeletedWhenTestFinishes(G_OBJECT(webkit_web_inspector_get_web_view(test->m_inspector)));
    g_assert_false(webkit_web_inspector_is_attached(test->m_inspector));
    Vector<InspectorTest::InspectorEvents>& events = test->m_events;
    g_assert_cmpint(events.size(), ==, 1);
    g_assert_cmpint(events[0], ==, InspectorTest::OpenWindow);
    test->m_events.clear();

    test->resizeViewAndAttach();
    g_assert_true(webkit_web_inspector_is_attached(test->m_inspector));
    g_assert_cmpuint(webkit_web_inspector_get_attached_height(test->m_inspector), >=, InspectorTest::gMinimumAttachedInspectorHeight);
    events = test->m_events;
    g_assert_cmpint(events.size(), ==, 1);
    g_assert_cmpint(events[0], ==, InspectorTest::Attach);
    test->m_events.clear();

    test->detachAndWaitUntilWindowOpened();
    g_assert_false(webkit_web_inspector_is_attached(test->m_inspector));
    events = test->m_events;
    g_assert_cmpint(events.size(), ==, 2);
    g_assert_cmpint(events[0], ==, InspectorTest::Detach);
    g_assert_cmpint(events[1], ==, InspectorTest::OpenWindow);
    test->m_events.clear();

    test->resizeViewAndAttach();
    g_assert_true(webkit_web_inspector_is_attached(test->m_inspector));
    test->m_events.clear();
    test->close();
    events = test->m_events;
    g_assert_cmpint(events.size(), ==, 2);
    g_assert_cmpint(events[0], ==, InspectorTest::Detach);
    g_assert_cmpint(events[1], ==, InspectorTest::Closed);
    test->m_events.clear();
}

static void testInspectorCustomContainerDestroyed(CustomInspectorTest* test, gconstpointer)
{
    test->showInWindowAndWaitUntilMapped(GTK_WINDOW_TOPLEVEL);
    test->resizeView(200, 200);
    test->loadHtml("<html><body><p>WebKitGTK Inspector test</p></body></html>", 0);
    test->waitUntilLoadFinished();

    test->show();
    test->assertObjectIsDeletedWhenTestFinishes(G_OBJECT(webkit_web_inspector_get_web_view(test->m_inspector)));
    g_assert_false(webkit_web_inspector_is_attached(test->m_inspector));

    test->m_events.clear();
    test->destroyWindow();
    Vector<InspectorTest::InspectorEvents>& events = test->m_events;
    g_assert_cmpint(events.size(), ==, 1);
    g_assert_cmpint(events[0], ==, InspectorTest::Closed);
    test->m_events.clear();
}

void beforeAll()
{
    InspectorTest::add("WebKitWebInspector", "default", testInspectorDefault);
    CustomInspectorTest::add("WebKitWebInspector", "manual-attach-detach", testInspectorManualAttachDetach);
    CustomInspectorTest::add("WebKitWebInspector", "custom-container-destroyed", testInspectorCustomContainerDestroyed);
}

void afterAll()
{
}
