/*
 *  Copyright (C) 2007 Holger Hans Peter Freyther
 *  Copyright (C) 2007 Alp Toker <alp@atoker.com>
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser 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
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 */

#include "config.h"
#include "Pasteboard.h"

#include "CString.h"
#include "DocumentFragment.h"
#include "Frame.h"
#include "NotImplemented.h"
#include "PlatformString.h"
#include "Image.h"
#include "RenderImage.h"
#include "KURL.h"
#include "markup.h"

#include <gtk/gtk.h>

namespace WebCore {

/* FIXME: we must get rid of this and use the enum in webkitwebview.h someway */
typedef enum
{
    WEBKIT_WEB_VIEW_TARGET_INFO_HTML = - 1,
    WEBKIT_WEB_VIEW_TARGET_INFO_TEXT = - 2
} WebKitWebViewTargetInfo;

class PasteboardSelectionData {
public:
    PasteboardSelectionData(gchar* text, gchar* markup)
        : m_text(text)
        , m_markup(markup) { }

    ~PasteboardSelectionData() {
        g_free(m_text);
        g_free(m_markup);
    }

    const gchar* text() const { return m_text; }
    const gchar* markup() const { return m_markup; }

private:
    gchar* m_text;
    gchar* m_markup;
};

static void clipboard_get_contents_cb(GtkClipboard *clipboard, GtkSelectionData *selection_data,
                                      guint info, gpointer data) {
    PasteboardSelectionData* clipboardData = reinterpret_cast<PasteboardSelectionData*>(data);
    ASSERT(clipboardData);
    if ((gint)info == WEBKIT_WEB_VIEW_TARGET_INFO_HTML) {
        gtk_selection_data_set(selection_data, selection_data->target, 8,
                               reinterpret_cast<const guchar*>(clipboardData->markup()),
                               g_utf8_strlen(clipboardData->markup(), -1));
    } else
        gtk_selection_data_set_text(selection_data, clipboardData->text(), -1);
}

static void clipboard_clear_contents_cb(GtkClipboard *clipboard, gpointer data) {
    PasteboardSelectionData* clipboardData = reinterpret_cast<PasteboardSelectionData*>(data);
    ASSERT(clipboardData);
    delete clipboardData;
}


Pasteboard* Pasteboard::generalPasteboard()
{
    static Pasteboard* pasteboard = new Pasteboard();
    return pasteboard;
}

Pasteboard::Pasteboard()
{
    notImplemented();
}

Pasteboard::~Pasteboard()
{
    delete m_helper;
}

void Pasteboard::setHelper(PasteboardHelper* helper)
{
    m_helper = helper;
}

void Pasteboard::writeSelection(Range* selectedRange, bool canSmartCopyOrDelete, Frame* frame)
{
    gchar* text = g_strdup(frame->selectedText().utf8().data());
    gchar* markup = g_strdup(createMarkup(selectedRange, 0, AnnotateForInterchange).utf8().data());
    PasteboardSelectionData* data = new PasteboardSelectionData(text, markup);

    gint n_targets;
    GtkTargetEntry* targets = gtk_target_table_new_from_list(m_helper->getCopyTargetList(frame), &n_targets);
    GtkClipboard* clipboard = m_helper->getClipboard(frame);
    gtk_clipboard_set_with_data(clipboard, targets, n_targets,
                                clipboard_get_contents_cb, clipboard_clear_contents_cb, data);
    gtk_target_table_free(targets, n_targets);
}

void Pasteboard::writeURL(const KURL& url, const String&, Frame* frame)
{
    if (url.isEmpty())
        return;

    GtkClipboard* clipboard = m_helper->getClipboard(frame);
    gtk_clipboard_set_text(clipboard, url.string().utf8().data(), url.string().utf8().length());
}

void Pasteboard::writeImage(Node* node, const KURL&, const String&)
{
    // TODO: Enable this when Image gets GdkPixbuf support

    /*
    GtkClipboard* clipboard = gtk_clipboard_get_for_display(gdk_display_get_default(), GDK_SELECTION_CLIPBOARD);

    ASSERT(node && node->renderer() && node->renderer()->isImage());
    RenderImage* renderer = static_cast<RenderImage*>(node->renderer());
    CachedImage* cachedImage = static_cast<CachedImage*>(renderer->cachedImage());
    ASSERT(cachedImage);
    Image* image = cachedImage->image();
    ASSERT(image);

    gtk_clipboard_set_image(clipboard, image->pixbuf());
    */

    notImplemented();
}

void Pasteboard::clear()
{
    GtkClipboard* clipboard = gtk_clipboard_get_for_display(gdk_display_get_default(), GDK_SELECTION_CLIPBOARD);

    gtk_clipboard_clear(clipboard);
}

bool Pasteboard::canSmartReplace()
{
    notImplemented();
    return false;
}

PassRefPtr<DocumentFragment> Pasteboard::documentFragment(Frame* frame, PassRefPtr<Range> context,
                                                          bool allowPlainText, bool& chosePlainText)
{
#if GTK_CHECK_VERSION(2,10,0)
    GdkAtom textHtml = gdk_atom_intern_static_string("text/html");
#else
    GdkAtom textHtml = gdk_atom_intern("text/html", false);
#endif
    GtkClipboard* clipboard = m_helper->getClipboard(frame);
    chosePlainText = false;

    if (GtkSelectionData* data = gtk_clipboard_wait_for_contents(clipboard, textHtml)) {
        ASSERT(data->data);
        String html = String::fromUTF8(reinterpret_cast<gchar*>(data->data), data->length * data->format / 8);
        gtk_selection_data_free(data);

        if (!html.isEmpty()) {
            RefPtr<DocumentFragment> fragment = createFragmentFromMarkup(frame->document(), html, "");
            if (fragment)
                return fragment.release();
        }
    }

    if (!allowPlainText)
        return 0;

    if (gchar* utf8 = gtk_clipboard_wait_for_text(clipboard)) {
        String text = String::fromUTF8(utf8);
        g_free(utf8);

        chosePlainText = true;
        RefPtr<DocumentFragment> fragment = createFragmentFromText(context.get(), text);
        if (fragment)
            return fragment.release();
    }

    return 0;
}

String Pasteboard::plainText(Frame* frame)
{
    GtkClipboard* clipboard = m_helper->getClipboard(frame);

    gchar* utf8 = gtk_clipboard_wait_for_text(clipboard);

    if (!utf8)
        return String();

    String text = String::fromUTF8(utf8);
    g_free(utf8);

    return text;
}

}
