/*
 * Copyright (C) 2020 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 COMPUTER, INC. ``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 COMPUTER, INC. OR
 * 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 "DragSource.h"

#if ENABLE(DRAG_SUPPORT) && !USE(GTK4)

#include "WebKitWebViewBasePrivate.h"
#include <WebCore/GRefPtrGtk.h>
#include <WebCore/GtkUtilities.h>
#include <gtk/gtk.h>

namespace WebKit {
using namespace WebCore;

enum DragTargetType { Markup, Text, Image, URIList, NetscapeURL, SmartPaste };

DragSource::DragSource(GtkWidget* webView)
    : m_webView(webView)
{
    g_signal_connect(m_webView, "drag-data-get", G_CALLBACK(+[](GtkWidget*, GdkDragContext* context, GtkSelectionData* data, guint info, guint, gpointer userData) {
        auto& drag = *static_cast<DragSource*>(userData);
        if (drag.m_drag.get() != context)
            return;

        switch (info) {
        case DragTargetType::Text:
            gtk_selection_data_set_text(data, drag.m_selectionData->text().utf8().data(), -1);
            break;
        case DragTargetType::Markup: {
            CString markup = drag.m_selectionData->markup().utf8();
            gtk_selection_data_set(data, gdk_atom_intern_static_string("text/html"), 8, reinterpret_cast<const guchar*>(markup.data()), markup.length());
            break;
        }
        case DragTargetType::URIList: {
            CString uriList = drag.m_selectionData->uriList().utf8();
            gtk_selection_data_set(data, gdk_atom_intern_static_string("text/uri-list"), 8, reinterpret_cast<const guchar*>(uriList.data()), uriList.length());
            break;
        }
        case DragTargetType::NetscapeURL: {
            CString urlString = drag.m_selectionData->url().string().utf8();
            GUniquePtr<gchar> url(g_strdup_printf("%s\n%s", urlString.data(), drag.m_selectionData->hasText() ? drag.m_selectionData->text().utf8().data() : urlString.data()));
            gtk_selection_data_set(data, gdk_atom_intern_static_string("_NETSCAPE_URL"), 8, reinterpret_cast<const guchar*>(url.get()), strlen(url.get()));
            break;
        }
        case DragTargetType::Image: {
            GRefPtr<GdkPixbuf> pixbuf = adoptGRef(drag.m_selectionData->image()->getGdkPixbuf());
            gtk_selection_data_set_pixbuf(data, pixbuf.get());
            break;
        }
        case DragTargetType::SmartPaste:
            gtk_selection_data_set_text(data, "", -1);
            break;
        }
    }), this);

    g_signal_connect(m_webView, "drag-end", G_CALLBACK(+[](GtkWidget*, GdkDragContext* context, gpointer userData) {
        auto& drag = *static_cast<DragSource*>(userData);
        if (drag.m_drag.get() != context)
            return;
        if (!drag.m_selectionData)
            return;

        drag.m_selectionData = WTF::nullopt;
        drag.m_drag = nullptr;

        GdkDevice* device = gdk_drag_context_get_device(context);
        int x = 0;
        int y = 0;
        gdk_device_get_window_at_position(device, &x, &y);
        int xRoot = 0;
        int yRoot = 0;
        gdk_device_get_position(device, nullptr, &xRoot, &yRoot);

        auto* page = webkitWebViewBaseGetPage(WEBKIT_WEB_VIEW_BASE(drag.m_webView));
        ASSERT(page);
        page->dragEnded({ x, y }, { xRoot, yRoot }, gdkDragActionToDragOperation(gdk_drag_context_get_selected_action(context)));
    }), this);
}

DragSource::~DragSource()
{
    g_signal_handlers_disconnect_by_data(m_webView, this);
}

void DragSource::begin(SelectionData&& selectionData, OptionSet<DragOperation> operationMask, RefPtr<ShareableBitmap>&& image)
{
    if (m_drag) {
        gtk_drag_cancel(m_drag.get());
        m_drag = nullptr;
    }

    m_selectionData = WTFMove(selectionData);

    GRefPtr<GtkTargetList> list = adoptGRef(gtk_target_list_new(nullptr, 0));
    if (m_selectionData->hasText())
        gtk_target_list_add_text_targets(list.get(), DragTargetType::Text);
    if (m_selectionData->hasMarkup())
        gtk_target_list_add(list.get(), gdk_atom_intern_static_string("text/html"), 0, DragTargetType::Markup);
    if (m_selectionData->hasURIList())
        gtk_target_list_add_uri_targets(list.get(), DragTargetType::URIList);
    if (m_selectionData->hasURL())
        gtk_target_list_add(list.get(), gdk_atom_intern_static_string("_NETSCAPE_URL"), 0, DragTargetType::NetscapeURL);
    if (m_selectionData->hasImage())
        gtk_target_list_add_image_targets(list.get(), DragTargetType::Image, TRUE);
    if (m_selectionData->canSmartReplace())
        gtk_target_list_add(list.get(), gdk_atom_intern_static_string("application/vnd.webkitgtk.smartpaste"), 0, DragTargetType::SmartPaste);

    m_drag = gtk_drag_begin_with_coordinates(m_webView, list.get(), dragOperationToGdkDragActions(operationMask), GDK_BUTTON_PRIMARY, nullptr, -1, -1);
    if (image) {
        RefPtr<cairo_surface_t> imageSurface(image->createCairoSurface());
        // Use the center of the drag image as hotspot.
        cairo_surface_set_device_offset(imageSurface.get(), -cairo_image_surface_get_width(imageSurface.get()) / 2, -cairo_image_surface_get_height(imageSurface.get()) / 2);
        gtk_drag_set_icon_surface(m_drag.get(), imageSurface.get());
    } else
        gtk_drag_set_icon_default(m_drag.get());
}

} // namespace WebKit

#endif // ENABLE(DRAG_SUPPORT) && !USE(GTK4)
