#include "treelandclipboard.h"

#include <QBuffer>
#include <QGuiApplication>

UOSAI_USE_NAMESPACE

TreelandClipboard::TreelandClipboard(QObject *parent) : BaseClipboard(parent)
{
    m_manager.reset(new DataControlDeviceV1ManagerV1);
    QObject::connect(m_manager.get(), &DataControlDeviceV1ManagerV1::activeChanged, this, [this]() {
        if (m_manager->isActive()) {
            auto waylandApp = qGuiApp->nativeInterface<QNativeInterface::QWaylandApplication>();
            if (!waylandApp) {
                return;
            }
            auto seat = waylandApp->seat();

            if (!seat)
                qFatal("Failed to get wl_seat frome QtWayland QPA!");

            m_device.reset(new DataControlDeviceV1(m_manager->get_data_device(seat)));

            connect(m_device.get(), &DataControlDeviceV1::receivedSelectionChanged, this, [this]() {
                if (!m_device->selection()) {
                    Q_EMIT changed(QClipboard::Clipboard);
                    // Q_EMIT selectWords();

                    if (m_device->m_receivedSelection) {
                        DataControlOfferV1 *offer = m_device->m_receivedSelection.get();
                        for (auto type : offer->formats()) {
                            if(type != "text/plain;charset=utf-8") continue;

                            QVariant data = offer->retrieveData(type);
                            // qWarning() << "----------"
                            //               "receivedSelectionChanged---"
                            //            << "type:=" << type << "data:= " << data;
                            clipText = data.toString();
                            if (isScribeWordsVisible() && type == "text/plain;charset=utf-8")
                                Q_EMIT selectWords();
                        }
                    }
                }
            });
            connect(m_device.get(), &DataControlDeviceV1::selectionChanged, this, [this]() {
                Q_EMIT changed(QClipboard::Clipboard);
                Q_EMIT selectWords();
            });

            connect(m_device.get(),
                    &DataControlDeviceV1::receivedPrimarySelectionChanged,
                    this,
                    [this]() {
                        if (!m_device->primarySelection()) {
                            Q_EMIT changed(QClipboard::Selection);

                            if (m_device->m_receivedPrimarySelection) {
                                DataControlOfferV1 *offer =
                                    m_device->m_receivedPrimarySelection.get();
                                for (auto type : offer->formats()) {
                                    if(type != "text/plain;charset=utf-8") continue;

                                    QVariant data = offer->retrieveData(type);
                                    // qWarning() << "----------"
                                    //               "receivedPrimarySelectionChanged"
                                    //            << "type:=" << type << "data:= " << data;
                                    clipText = data.toString();
                                    if (isScribeWordsVisible() && type == "text/plain;charset=utf-8")
                                        Q_EMIT selectWords();
                                }
                            }
                        }
                    });
            connect(m_device.get(), &DataControlDeviceV1::primarySelectionChanged, this, [this]() {
                Q_EMIT changed(QClipboard::Selection);
                Q_EMIT selectWords();
            });

        } else {
            m_device.reset();
        }
    });

    m_manager->instantiate();
}

bool TreelandClipboard::isValid()
{
    return m_manager && m_manager->isInitialized();
}

QString TreelandClipboard::getClipText()
{
    return clipText;
}

void TreelandClipboard::clearClipText()
{
    clipText = "";
}

bool TreelandClipboard::isScribeWordsVisible()
{
    return !clipText.trimmed().isEmpty();
}

void TreelandClipboard::blockChangedSignal(bool block)
{
    m_device->blockSignals(block);
}
