/*
 * Copyright (C) 2010 Martin Robinson <mrobinson@webkit.org>
 * Copyright (C) Igalia S.L.
 * Copyright (C) 2013 Collabora Ltd.
 * 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.
 *
 */
#include "config.h"
#include "PasteboardHelper.h"

#include "BitmapImage.h"
#include "GtkVersioning.h"
#include "SelectionData.h"
#include <gtk/gtk.h>
#include <wtf/SetForScope.h>
#include <wtf/glib/GUniquePtr.h>
#include <wtf/text/CString.h>

namespace WebCore {

static GdkAtom textPlainAtom;
static GdkAtom markupAtom;
static GdkAtom netscapeURLAtom;
static GdkAtom uriListAtom;
static GdkAtom smartPasteAtom;
static GdkAtom unknownAtom;

static const String gMarkupPrefix = ASCIILiteral("<meta http-equiv=\"content-type\" content=\"text/html; charset=utf-8\">");

static void removeMarkupPrefix(String& markup)
{
    // The markup prefix is not harmful, but we remove it from the string anyway, so that
    // we can have consistent results with other ports during the layout tests.
    if (markup.startsWith(gMarkupPrefix))
        markup.remove(0, gMarkupPrefix.length());
}

PasteboardHelper& PasteboardHelper::singleton()
{
    static PasteboardHelper helper;
    return helper;
}

PasteboardHelper::PasteboardHelper()
    : m_targetList(adoptGRef(gtk_target_list_new(nullptr, 0)))
{
    textPlainAtom = gdk_atom_intern_static_string("text/plain;charset=utf-8");
    markupAtom = gdk_atom_intern_static_string("text/html");
    netscapeURLAtom = gdk_atom_intern_static_string("_NETSCAPE_URL");
    uriListAtom = gdk_atom_intern_static_string("text/uri-list");
    smartPasteAtom = gdk_atom_intern_static_string("application/vnd.webkitgtk.smartpaste");
    unknownAtom = gdk_atom_intern_static_string("application/vnd.webkitgtk.unknown");

    gtk_target_list_add_text_targets(m_targetList.get(), PasteboardHelper::TargetTypeText);
    gtk_target_list_add(m_targetList.get(), markupAtom, 0, PasteboardHelper::TargetTypeMarkup);
    gtk_target_list_add_uri_targets(m_targetList.get(), PasteboardHelper::TargetTypeURIList);
    gtk_target_list_add(m_targetList.get(), netscapeURLAtom, 0, PasteboardHelper::TargetTypeNetscapeURL);
    gtk_target_list_add_image_targets(m_targetList.get(), PasteboardHelper::TargetTypeImage, TRUE);
    gtk_target_list_add(m_targetList.get(), unknownAtom, 0, PasteboardHelper::TargetTypeUnknown);
}

PasteboardHelper::~PasteboardHelper() = default;

GtkTargetList* PasteboardHelper::targetList() const
{
    return m_targetList.get();
}

static String selectionDataToUTF8String(GtkSelectionData* data)
{
    if (!gtk_selection_data_get_length(data))
        return String();

    // g_strndup guards against selection data that is not null-terminated.
    GUniquePtr<gchar> markupString(g_strndup(reinterpret_cast<const char*>(gtk_selection_data_get_data(data)), gtk_selection_data_get_length(data)));
    return String::fromUTF8(markupString.get());
}

void PasteboardHelper::getClipboardContents(GtkClipboard* clipboard, SelectionData& selection)
{
    if (gtk_clipboard_wait_is_text_available(clipboard)) {
        GUniquePtr<gchar> textData(gtk_clipboard_wait_for_text(clipboard));
        if (textData)
            selection.setText(String::fromUTF8(textData.get()));
    }

    if (gtk_clipboard_wait_is_target_available(clipboard, markupAtom)) {
        if (GtkSelectionData* data = gtk_clipboard_wait_for_contents(clipboard, markupAtom)) {
            String markup(selectionDataToUTF8String(data));
            removeMarkupPrefix(markup);
            selection.setMarkup(markup);
            gtk_selection_data_free(data);
        }
    }

    if (gtk_clipboard_wait_is_target_available(clipboard, uriListAtom)) {
        if (GtkSelectionData* data = gtk_clipboard_wait_for_contents(clipboard, uriListAtom)) {
            selection.setURIList(selectionDataToUTF8String(data));
            gtk_selection_data_free(data);
        }
    }

#ifndef GTK_API_VERSION_2
    if (gtk_clipboard_wait_is_image_available(clipboard)) {
        if (GRefPtr<GdkPixbuf> pixbuf = adoptGRef(gtk_clipboard_wait_for_image(clipboard))) {
            RefPtr<cairo_surface_t> surface = adoptRef(gdk_cairo_surface_create_from_pixbuf(pixbuf.get(), 1, nullptr));
            Ref<Image> image = BitmapImage::create(WTFMove(surface));
            selection.setImage(image.ptr());
        }
    }
#endif

    selection.setCanSmartReplace(gtk_clipboard_wait_is_target_available(clipboard, smartPasteAtom));
}

GRefPtr<GtkTargetList> PasteboardHelper::targetListForSelectionData(const SelectionData& selection)
{
    GRefPtr<GtkTargetList> list = adoptGRef(gtk_target_list_new(nullptr, 0));

    if (selection.hasText())
        gtk_target_list_add_text_targets(list.get(), TargetTypeText);

    if (selection.hasMarkup())
        gtk_target_list_add(list.get(), markupAtom, 0, TargetTypeMarkup);

    if (selection.hasURIList()) {
        gtk_target_list_add_uri_targets(list.get(), TargetTypeURIList);
        gtk_target_list_add(list.get(), netscapeURLAtom, 0, TargetTypeNetscapeURL);
    }

    if (selection.hasImage())
        gtk_target_list_add_image_targets(list.get(), TargetTypeImage, TRUE);

    if (selection.hasUnknownTypeData())
        gtk_target_list_add(list.get(), unknownAtom, 0, TargetTypeUnknown);

    if (selection.canSmartReplace())
        gtk_target_list_add(list.get(), smartPasteAtom, 0, TargetTypeSmartPaste);

    return list;
}

void PasteboardHelper::fillSelectionData(const SelectionData& selection, unsigned info, GtkSelectionData* selectionData)
{
    if (info == TargetTypeText)
        gtk_selection_data_set_text(selectionData, selection.text().utf8().data(), -1);

    else if (info == TargetTypeMarkup) {
        // Some Linux applications refuse to accept pasted markup unless it is
        // prefixed by a content-type meta tag.
        CString markup = String(gMarkupPrefix + selection.markup()).utf8();
        gtk_selection_data_set(selectionData, markupAtom, 8, reinterpret_cast<const guchar*>(markup.data()), markup.length());

    } else if (info == TargetTypeURIList) {
        CString uriList = selection.uriList().utf8();
        gtk_selection_data_set(selectionData, uriListAtom, 8, reinterpret_cast<const guchar*>(uriList.data()), uriList.length());

    } else if (info == TargetTypeNetscapeURL && selection.hasURL()) {
        String url(selection.url());
        String result(url);
        result.append("\n");

        if (selection.hasText())
            result.append(selection.text());
        else
            result.append(url);

        GUniquePtr<gchar> resultData(g_strdup(result.utf8().data()));
        gtk_selection_data_set(selectionData, netscapeURLAtom, 8, reinterpret_cast<const guchar*>(resultData.get()), strlen(resultData.get()));

    } else if (info == TargetTypeImage && selection.hasImage()) {
        GRefPtr<GdkPixbuf> pixbuf = adoptGRef(selection.image()->getGdkPixbuf());
        gtk_selection_data_set_pixbuf(selectionData, pixbuf.get());

    } else if (info == TargetTypeSmartPaste)
        gtk_selection_data_set_text(selectionData, "", -1);

    else if (info == TargetTypeUnknown) {
        GVariantBuilder builder;
        g_variant_builder_init(&builder, G_VARIANT_TYPE_ARRAY);

        for (auto& it : selection.unknownTypes()) {
            GUniquePtr<gchar> dictItem(g_strdup_printf("{'%s', '%s'}", it.key.utf8().data(), it.value.utf8().data()));
            g_variant_builder_add_parsed(&builder, dictItem.get());
        }

        GRefPtr<GVariant> variant = g_variant_builder_end(&builder);
        GUniquePtr<gchar> serializedVariant(g_variant_print(variant.get(), TRUE));
        gtk_selection_data_set(selectionData, unknownAtom, 1, reinterpret_cast<const guchar*>(serializedVariant.get()), strlen(serializedVariant.get()));
    }
}

void PasteboardHelper::fillSelectionData(GtkSelectionData* data, unsigned /* info */, SelectionData& selection)
{
    if (gtk_selection_data_get_length(data) < 0)
        return;

    GdkAtom target = gtk_selection_data_get_target(data);
    if (target == textPlainAtom)
        selection.setText(selectionDataToUTF8String(data));
    else if (target == markupAtom) {
        String markup(selectionDataToUTF8String(data));
        removeMarkupPrefix(markup);
        selection.setMarkup(markup);
    } else if (target == uriListAtom) {
        selection.setURIList(selectionDataToUTF8String(data));
    } else if (target == netscapeURLAtom) {
        String urlWithLabel(selectionDataToUTF8String(data));
        Vector<String> pieces;
        urlWithLabel.split('\n', pieces);

        // Give preference to text/uri-list here, as it can hold more
        // than one URI but still take  the label if there is one.
        if (!selection.hasURIList() && !pieces.isEmpty())
            selection.setURIList(pieces[0]);
        if (pieces.size() > 1)
            selection.setText(pieces[1]);
    } else if (target == unknownAtom && gtk_selection_data_get_length(data)) {
        GRefPtr<GVariant> variant = g_variant_new_parsed(reinterpret_cast<const char*>(gtk_selection_data_get_data(data)));

        GUniqueOutPtr<gchar> key;
        GUniqueOutPtr<gchar> value;
        GVariantIter iter;

        g_variant_iter_init(&iter, variant.get());
        while (g_variant_iter_next(&iter, "{ss}", &key.outPtr(), &value.outPtr()))
            selection.setUnknownTypeData(key.get(), value.get());
    }
}

Vector<GdkAtom> PasteboardHelper::dropAtomsForContext(GtkWidget* widget, GdkDragContext* context)
{
    // Always search for these common atoms.
    Vector<GdkAtom> dropAtoms;
    dropAtoms.append(textPlainAtom);
    dropAtoms.append(markupAtom);
    dropAtoms.append(uriListAtom);
    dropAtoms.append(netscapeURLAtom);
    dropAtoms.append(unknownAtom);

    // For images, try to find the most applicable image type.
    GRefPtr<GtkTargetList> list = adoptGRef(gtk_target_list_new(0, 0));
    gtk_target_list_add_image_targets(list.get(), TargetTypeImage, TRUE);
    GdkAtom atom = gtk_drag_dest_find_target(widget, context, list.get());
    if (atom != GDK_NONE)
        dropAtoms.append(atom);

    return dropAtoms;
}

static SelectionData* settingClipboardSelection;

struct ClipboardSetData {
    ClipboardSetData(SelectionData& selection, WTF::Function<void()>&& selectionClearedCallback)
        : selectionData(selection)
        , selectionClearedCallback(WTFMove(selectionClearedCallback))
    {
    }

    ~ClipboardSetData() = default;

    Ref<SelectionData> selectionData;
    WTF::Function<void()> selectionClearedCallback;
};

static void getClipboardContentsCallback(GtkClipboard*, GtkSelectionData *selectionData, guint info, gpointer userData)
{
    auto* data = static_cast<ClipboardSetData*>(userData);
    PasteboardHelper::singleton().fillSelectionData(data->selectionData, info, selectionData);
}

static void clearClipboardContentsCallback(GtkClipboard*, gpointer userData)
{
    std::unique_ptr<ClipboardSetData> data(static_cast<ClipboardSetData*>(userData));
    if (data->selectionClearedCallback)
        data->selectionClearedCallback();
}

void PasteboardHelper::writeClipboardContents(GtkClipboard* clipboard, const SelectionData& selection, WTF::Function<void()>&& primarySelectionCleared)
{
    GRefPtr<GtkTargetList> list = targetListForSelectionData(selection);

    int numberOfTargets;
    GtkTargetEntry* table = gtk_target_table_new_from_list(list.get(), &numberOfTargets);

    if (numberOfTargets > 0 && table) {
        SetForScope<SelectionData*> change(settingClipboardSelection, const_cast<SelectionData*>(&selection));
        auto data = std::make_unique<ClipboardSetData>(*settingClipboardSelection, WTFMove(primarySelectionCleared));
        if (gtk_clipboard_set_with_data(clipboard, table, numberOfTargets, getClipboardContentsCallback, clearClipboardContentsCallback, data.get())) {
            gtk_clipboard_set_can_store(clipboard, nullptr, 0);
            // When gtk_clipboard_set_with_data() succeeds clearClipboardContentsCallback takes the ownership of data, so we leak it here.
            data.release();
        }
    } else
        gtk_clipboard_clear(clipboard);

    if (table)
        gtk_target_table_free(table, numberOfTargets);
}

}

