/*
    SPDX-FileCopyrightText: 2014-2023 Anne Jan Brouwer <brouwer@annejan.com>
    SPDX-FileCopyrightText: 2018 Claudio Maradonna <penguyman@stronzi.org>
    SPDX-FileCopyrightText: 2023 g10 Code GmbH
    SPDX-FileContributor: Sune Stolborg Vuorela <sune@vuorela.dk>

    SPDX-License-Identifier: GPL-3.0-or-later
*/

#include "clipboardhelper.h"
#include "config.h"

#include <KLocalizedString>

#include <QApplication>
#include <QClipboard>
#include <QDialog>
#include <QLabel>
#include <QMainWindow>
#include <QMimeData>
#include <QPixmap>
#include <QStatusBar>
#include <QVBoxLayout>
#ifdef Q_OS_UNIX
#include <QProcess>
#include <QProcessEnvironment>
#endif

using namespace Qt::StringLiterals;

ClipboardHelper::ClipboardHelper(QMainWindow *mainWindow)
    : QObject(mainWindow)
    , m_mainWindow(mainWindow)
    , clippedText(QString())
{
    setClipboardTimer();
    clearClipboardTimer.setSingleShot(true);
    connect(&clearClipboardTimer, &QTimer::timeout, this, &ClipboardHelper::clearClipboard);
}

ClipboardHelper::~ClipboardHelper() = default;

void ClipboardHelper::setClippedText(const QString &password)
{
    clippedText = password;
}
void ClipboardHelper::clearClippedText()
{
    clippedText = QString{};
}

void ClipboardHelper::setClipboardTimer()
{
    clearClipboardTimer.setInterval(1000 * Config::self()->clipboardAutoClearTime());
}

/**
 * Clears the clipboard if we filled it
 */
void ClipboardHelper::clearClipboard()
{
    QClipboard *clipboard = QApplication::clipboard();
    bool cleared = false;
    if (clippedText == clipboard->text(QClipboard::Selection)) {
        clipboard->clear(QClipboard::Selection);
        clipboard->setText(QString{}, QClipboard::Selection);
        cleared = true;
    }
    if (clippedText == clipboard->text(QClipboard::Clipboard)) {
        clipboard->clear(QClipboard::Clipboard);
        cleared = true;
    }

#ifdef Q_OS_UNIX
    // Gnome Wayland doesn't let apps modify the clipboard when not in focus, so force clear
    if (QProcessEnvironment::systemEnvironment().contains(u"WAYLAND_DISPLAY"_s)) {
        QProcess::startDetached(u"wl-copy"_s, {u"-c"_s});
    }
#endif
    if (cleared) {
        Q_EMIT showMessage(i18nc("@info:status", "Clipboard cleared."), 2000);
    }

    clippedText.clear();
}

/**
 * @brief MainWindow::copyTextToClipboard copies text to your clipboard
 * @param text
 */
void ClipboardHelper::copyTextToClipboard(const QString &text)
{
    auto *clipboard = QApplication::clipboard();
    if (!clipboard) {
        qWarning("Unable to access the clipboard.");
        return;
    }

    auto *mime = new QMimeData;
    mime->setText(text);
#if defined(Q_OS_UNIX)
    mime->setData(u"x-kde-passwordManagerHint"_s, QByteArrayLiteral("secret"));
#elif defined(Q_OS_WIN)
    mime->setData(u"ExcludeClipboardContentFromMonitorProcessing"_s, QByteArrayLiteral("1"));
    mime->setData(u"CanIncludeInClipboardHistory"_s, {4, '\0'});
    mime->setData(u"CanUploadToCloudClipboard"_s, {4, '\0'});
#endif

    if (clipboard->supportsSelection()) {
        clipboard->setMimeData(mime, QClipboard::Selection);
    }
    clipboard->setMimeData(mime, QClipboard::Clipboard);

    clippedText = text;
    Q_EMIT showMessage(i18n("Copied to clipboard"), 2000);
    if (Config::self()->clipboardAutoClearEnabled()) {
        clearClipboardTimer.start();
    }
}
