/*
 * GTK UI -- clipboard support
 *
 * Copyright (C) 2021 Gerd Hoffmann <kraxel@redhat.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program 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
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, see <http://www.gnu.org/licenses/>.
 *
 */

#include "qemu/osdep.h"
#include "qemu-common.h"
#include "qemu/main-loop.h"

#include "ui/gtk.h"

static QemuClipboardSelection gd_find_selection(GtkDisplayState *gd,
                                                GtkClipboard *clipboard)
{
    QemuClipboardSelection s;

    for (s = 0; s < QEMU_CLIPBOARD_SELECTION__COUNT; s++) {
        if (gd->gtkcb[s] == clipboard) {
            return s;
        }
    }
    return QEMU_CLIPBOARD_SELECTION_CLIPBOARD;
}

static void gd_clipboard_get_data(GtkClipboard     *clipboard,
                                  GtkSelectionData *selection_data,
                                  guint             selection_info,
                                  gpointer          data)
{
    GtkDisplayState *gd = data;
    QemuClipboardSelection s = gd_find_selection(gd, clipboard);
    QemuClipboardType type = QEMU_CLIPBOARD_TYPE_TEXT;
    g_autoptr(QemuClipboardInfo) info = NULL;

    info = qemu_clipboard_info_ref(qemu_clipboard_info(s));

    qemu_clipboard_request(info, type);
    while (info == qemu_clipboard_info(s) &&
           info->types[type].available &&
           info->types[type].data == NULL) {
        main_loop_wait(false);
    }

    if (info == qemu_clipboard_info(s) && gd->cbowner[s]) {
        gtk_selection_data_set_text(selection_data,
                                    info->types[type].data,
                                    info->types[type].size);
    } else {
        /* clipboard owner changed while waiting for the data */
    }
}

static void gd_clipboard_clear(GtkClipboard *clipboard,
                               gpointer data)
{
    GtkDisplayState *gd = data;
    QemuClipboardSelection s = gd_find_selection(gd, clipboard);

    gd->cbowner[s] = false;
}

static void gd_clipboard_notify(Notifier *notifier, void *data)
{
    GtkDisplayState *gd = container_of(notifier, GtkDisplayState, cbpeer.update);
    QemuClipboardInfo *info = data;
    QemuClipboardSelection s = info->selection;
    bool self_update = info->owner == &gd->cbpeer;

    if (info != qemu_clipboard_info(s)) {
        gd->cbpending[s] = 0;
        if (!self_update) {
            GtkTargetList *list;
            GtkTargetEntry *targets;
            gint n_targets;

            list = gtk_target_list_new(NULL, 0);
            if (info->types[QEMU_CLIPBOARD_TYPE_TEXT].available) {
                gtk_target_list_add_text_targets(list, 0);
            }
            targets = gtk_target_table_new_from_list(list, &n_targets);

            gtk_clipboard_clear(gd->gtkcb[s]);
            gd->cbowner[s] = true;
            gtk_clipboard_set_with_data(gd->gtkcb[s],
                                        targets, n_targets,
                                        gd_clipboard_get_data,
                                        gd_clipboard_clear,
                                        gd);

            gtk_target_table_free(targets, n_targets);
            gtk_target_list_unref(list);
        }
        return;
    }

    if (self_update) {
        return;
    }

    /*
     * Clipboard got updated, with data probably.  No action here, we
     * are waiting for updates in gd_clipboard_get_data().
     */
}

static void gd_clipboard_request(QemuClipboardInfo *info,
                                 QemuClipboardType type)
{
    GtkDisplayState *gd = container_of(info->owner, GtkDisplayState, cbpeer);
    char *text;

    switch (type) {
    case QEMU_CLIPBOARD_TYPE_TEXT:
        text = gtk_clipboard_wait_for_text(gd->gtkcb[info->selection]);
        if (text) {
            qemu_clipboard_set_data(&gd->cbpeer, info, type,
                                    strlen(text), text, true);
            g_free(text);
        }
        break;
    default:
        break;
    }
}

static void gd_owner_change(GtkClipboard *clipboard,
                            GdkEvent *event,
                            gpointer data)
{
    GtkDisplayState *gd = data;
    QemuClipboardSelection s = gd_find_selection(gd, clipboard);
    QemuClipboardInfo *info;

    if (gd->cbowner[s]) {
        /* ignore notifications about our own grabs */
        return;
    }


    switch (event->owner_change.reason) {
    case GDK_OWNER_CHANGE_NEW_OWNER:
        info = qemu_clipboard_info_new(&gd->cbpeer, s);
        if (gtk_clipboard_wait_is_text_available(clipboard)) {
            info->types[QEMU_CLIPBOARD_TYPE_TEXT].available = true;
        }

        qemu_clipboard_update(info);
        qemu_clipboard_info_unref(info);
        break;
    default:
        qemu_clipboard_peer_release(&gd->cbpeer, s);
        gd->cbowner[s] = false;
        break;
    }
}

void gd_clipboard_init(GtkDisplayState *gd)
{
    gd->cbpeer.name = "gtk";
    gd->cbpeer.update.notify = gd_clipboard_notify;
    gd->cbpeer.request = gd_clipboard_request;
    qemu_clipboard_peer_register(&gd->cbpeer);

    gd->gtkcb[QEMU_CLIPBOARD_SELECTION_CLIPBOARD] =
        gtk_clipboard_get(GDK_SELECTION_CLIPBOARD);
    gd->gtkcb[QEMU_CLIPBOARD_SELECTION_PRIMARY] =
        gtk_clipboard_get(GDK_SELECTION_PRIMARY);
    gd->gtkcb[QEMU_CLIPBOARD_SELECTION_SECONDARY] =
        gtk_clipboard_get(GDK_SELECTION_SECONDARY);

    g_signal_connect(gd->gtkcb[QEMU_CLIPBOARD_SELECTION_CLIPBOARD],
                     "owner-change", G_CALLBACK(gd_owner_change), gd);
    g_signal_connect(gd->gtkcb[QEMU_CLIPBOARD_SELECTION_PRIMARY],
                     "owner-change", G_CALLBACK(gd_owner_change), gd);
    g_signal_connect(gd->gtkcb[QEMU_CLIPBOARD_SELECTION_SECONDARY],
                     "owner-change", G_CALLBACK(gd_owner_change), gd);
}
