/****************************************************************************
**
** Copyright (C) 2019 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtWaylandCompositor module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:GPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 or (at your option) any later version
** approved by the KDE Free Qt Foundation. The licenses are as published by
** the Free Software Foundation and appearing in the file LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include "qwltexturesharingextension_p.h"

#include <QWaylandSurface>

#include <QDebug>

#include <QQuickWindow>

#include <QPainter>
#include <QPen>
#include <QTimer>

#include <QtGui/private/qtexturefilereader_p.h>
#include <QtGui/QOpenGLTexture>
#include <QtGui/QImageReader>

#include <QtQuick/QSGTexture>
#include <QQmlContext>
#include <QThread>

QT_BEGIN_NAMESPACE

class SharedTexture : public QSGTexture
{
    Q_OBJECT
public:
    SharedTexture(QtWayland::ServerBuffer *buffer);

    int textureId() const override;
    QSize textureSize() const override;
    bool hasAlphaChannel() const override;
    bool hasMipmaps() const override;

    void bind() override;

private:
    void updateGLTexture() const;
    QtWayland::ServerBuffer *m_buffer = nullptr;
    mutable QOpenGLTexture *m_tex = nullptr;
};

SharedTexture::SharedTexture(QtWayland::ServerBuffer *buffer)
    : m_buffer(buffer), m_tex(nullptr)
{
}

int SharedTexture::textureId() const
{
    updateGLTexture();
    return m_tex ? m_tex->textureId() : 0;
}

QSize SharedTexture::textureSize() const
{
    updateGLTexture();
    return m_tex ? QSize(m_tex->width(), m_tex->height()) : QSize();
}

bool SharedTexture::hasAlphaChannel() const
{
    return true;
}

bool SharedTexture::hasMipmaps() const
{
    updateGLTexture();
    return m_tex ? (m_tex->mipLevels() > 1) : false;
}

void SharedTexture::bind()
{
    updateGLTexture();
    if (m_tex)
        m_tex->bind();
}

inline void SharedTexture::updateGLTexture() const
{
    if (!m_tex && m_buffer)
        m_tex = m_buffer->toOpenGlTexture();
}

class SharedTextureFactory : public QQuickTextureFactory
{
public:
    SharedTextureFactory(const QtWayland::ServerBuffer *buffer)
        : m_buffer(buffer)
    {
    }

    ~SharedTextureFactory() override
    {
        if (m_buffer && !QCoreApplication::closingDown())
            const_cast<QtWayland::ServerBuffer*>(m_buffer)->releaseOpenGlTexture();
    }

   QSize textureSize() const override
    {
        return m_buffer ? m_buffer->size() : QSize();
    }

    int textureByteCount() const override
    {
        return m_buffer ? (m_buffer->size().width() * m_buffer->size().height() * 4) : 0;
    }

    QSGTexture *createTexture(QQuickWindow *) const override
    {
        return new SharedTexture(const_cast<QtWayland::ServerBuffer *>(m_buffer));
    }

private:
    const QtWayland::ServerBuffer *m_buffer = nullptr;
};

class SharedTextureImageResponse : public QQuickImageResponse
{
    Q_OBJECT
public:
    SharedTextureImageResponse(QWaylandTextureSharingExtension *extension, const QString &id)
        : m_id(id)
    {
        if (extension)
            doRequest(extension);
    }

    void doRequest(QWaylandTextureSharingExtension *extension)
    {
        m_extension = extension;
        connect(extension, &QWaylandTextureSharingExtension::bufferResult, this, &SharedTextureImageResponse::doResponse);
        QMetaObject::invokeMethod(extension, [this] { m_extension->requestBuffer(m_id); }, Qt::AutoConnection);
    }

    QQuickTextureFactory *textureFactory() const override
    {
        if (m_buffer) {
//            qDebug() << "Creating shared buffer texture for" << m_id;
            return new SharedTextureFactory(m_buffer);
        }
//        qDebug() << "Shared buffer NOT found for" << m_id;
        m_errorString = QLatin1String("Shared buffer not found");
        return nullptr;
    }

    QString errorString() const override
    {
        return m_errorString;
    }

public slots:
    void doResponse(const QString &key, QtWayland::ServerBuffer *buffer)
    {
        if (key != m_id)
            return; //somebody else's texture

        m_buffer = buffer;

        if (m_extension)
            disconnect(m_extension, &QWaylandTextureSharingExtension::bufferResult, this, &SharedTextureImageResponse::doResponse);

        emit finished();
    }

private:
    QString m_id;
    QWaylandTextureSharingExtension *m_extension = nullptr;
    mutable QString m_errorString;
    QtWayland::ServerBuffer *m_buffer = nullptr;
};

QWaylandSharedTextureProvider::QWaylandSharedTextureProvider()
{
}

QWaylandSharedTextureProvider::~QWaylandSharedTextureProvider()
{
}

QQuickImageResponse *QWaylandSharedTextureProvider::requestImageResponse(const QString &id, const QSize &requestedSize)
{
    Q_UNUSED(requestedSize);

//    qDebug() << "Provider: got request for" << id;

    auto *extension = QWaylandTextureSharingExtension::self();
    auto *response = new SharedTextureImageResponse(extension, id);
    if (!extension)
        m_pendingResponses << response;

    return response;
}

void QWaylandSharedTextureProvider::setExtensionReady(QWaylandTextureSharingExtension *extension)
{
    for (auto *response : qAsConst(m_pendingResponses))
        response->doRequest(extension);
    m_pendingResponses.clear();
    m_pendingResponses.squeeze();
}

QWaylandTextureSharingExtension *QWaylandTextureSharingExtension::s_self = nullptr; // theoretical race conditions, but OK as long as we don't delete it while we are running

QWaylandTextureSharingExtension::QWaylandTextureSharingExtension()
{
    s_self = this;
}

QWaylandTextureSharingExtension::QWaylandTextureSharingExtension(QWaylandCompositor *compositor)
    :QWaylandCompositorExtensionTemplate(compositor)
{
    s_self = this;
}

QWaylandTextureSharingExtension::~QWaylandTextureSharingExtension()
{
    //qDebug() << Q_FUNC_INFO;
    //dumpBufferInfo();

    for (auto b : m_server_buffers)
        delete b.buffer;

    if (s_self == this)
        s_self = nullptr;
}

void QWaylandTextureSharingExtension::setImageSearchPath(const QString &path)
{
    m_image_dirs = path.split(QLatin1Char(';'));

    for (auto it = m_image_dirs.begin(); it != m_image_dirs.end(); ++it)
        if (!(*it).endsWith(QLatin1Char('/')))
            (*it) += QLatin1Char('/');
}

void QWaylandTextureSharingExtension::initialize()
{
    QWaylandCompositorExtensionTemplate::initialize();
    QWaylandCompositor *compositor = static_cast<QWaylandCompositor *>(extensionContainer());
    init(compositor->display(), 1);

    QString image_search_path = qEnvironmentVariable("QT_WAYLAND_SHAREDTEXTURE_SEARCH_PATH");
    if (!image_search_path.isEmpty())
        setImageSearchPath(image_search_path);

    if (m_image_dirs.isEmpty())
        m_image_dirs << QLatin1String(":/") << QLatin1String("./");

    auto suffixes = QTextureFileReader::supportedFileFormats();
    suffixes.append(QImageReader::supportedImageFormats());
    for (auto ext : qAsConst(suffixes))
        m_image_suffixes << QLatin1Char('.') + QString::fromLatin1(ext);

    //qDebug() << "m_image_suffixes" << m_image_suffixes << "m_image_dirs" << m_image_dirs;

    auto *ctx = QQmlEngine::contextForObject(this);
    if (ctx) {
        QQmlEngine *engine = ctx->engine();
        if (engine) {
            auto *provider = static_cast<QWaylandSharedTextureProvider*>(engine->imageProvider(QLatin1String("wlshared")));
            if (provider)
                provider->setExtensionReady(this);
        }
    }
}

QString QWaylandTextureSharingExtension::getExistingFilePath(const QString &key) const
{
    // The default search path blocks absolute pathnames, but this does not prevent relative
    // paths containing '../'. We handle that here, at the price of also blocking directory
    // names ending with two or more dots.

    if (key.contains(QLatin1String("../")))
        return QString();

    for (auto dir : m_image_dirs) {
        QString path = dir + key;
        if (QFileInfo::exists(path))
            return path;
    }

    for (auto dir : m_image_dirs) {
        for (auto ext : m_image_suffixes) {
            QString fp = dir + key + ext;
            //qDebug() << "trying" << fp;
            if (QFileInfo::exists(fp))
                return fp;
        }
    }
    return QString();
}

QtWayland::ServerBuffer *QWaylandTextureSharingExtension::getBuffer(const QString &key)
{
    if (!initServerBufferIntegration())
        return nullptr;

//qDebug() << "getBuffer" << key;

    QtWayland::ServerBuffer *buffer = nullptr;

    if ((buffer = m_server_buffers.value(key).buffer))
        return buffer;

    QByteArray pixelData;
    QSize size;
    uint glInternalFormat = GL_NONE;

    if (customPixelData(key, &pixelData, &size, &glInternalFormat)) {
        if (!pixelData.isEmpty()) {
            buffer = m_server_buffer_integration->createServerBufferFromData(pixelData, size, glInternalFormat);
            if (!buffer)
                qWarning() << "QWaylandTextureSharingExtension: could not create buffer from custom data for key:" << key;
        }
    } else {
        QString pathName = getExistingFilePath(key);
        //qDebug() << "pathName" << pathName;
        if (pathName.isEmpty())
            return nullptr;

        buffer = getCompressedBuffer(pathName);
        //qDebug() << "getCompressedBuffer" << buffer;

        if (!buffer) {
            QImage img(pathName);
            if (!img.isNull()) {
                img = img.convertToFormat(QImage::Format_RGBA8888_Premultiplied);
                buffer = m_server_buffer_integration->createServerBufferFromImage(img, QtWayland::ServerBuffer::RGBA32);
            }
            //qDebug() << "createServerBufferFromImage" << buffer;
        }
    }
    if (buffer)
        m_server_buffers.insert(key, BufferInfo(buffer));

    //qDebug() << ">>>>" << key << buffer;

    return buffer;
}

// Compositor requesting image for its own UI
void QWaylandTextureSharingExtension::requestBuffer(const QString &key)
{
    //qDebug() << "requestBuffer" << key;

    if (thread() != QThread::currentThread())
        qWarning("QWaylandTextureSharingExtension::requestBuffer() called from outside main thread: possible race condition");

    auto *buffer = getBuffer(key);

    if (buffer)
        m_server_buffers[key].usedLocally = true;

    //dumpBufferInfo();

    emit bufferResult(key, buffer);
}

void QWaylandTextureSharingExtension::zqt_texture_sharing_v1_request_image(Resource *resource, const QString &key)
{
    //qDebug() << "texture_sharing_request_image" << key;
    auto *buffer = getBuffer(key);
    if (buffer) {
        struct ::wl_client *client = resource->client();
        struct ::wl_resource *buffer_resource = buffer->resourceForClient(client);
        //qDebug() << "          server_buffer resource" << buffer_resource;
        if (buffer_resource)
            send_provide_buffer(resource->handle, buffer_resource, key);
        else
            qWarning() << "QWaylandTextureSharingExtension: no buffer resource for client";
    } else {
        send_image_failed(resource->handle, key, QString());
    }
    //dumpBufferInfo();
}

void QWaylandTextureSharingExtension::zqt_texture_sharing_v1_abandon_image(Resource *resource, const QString &key)
{
    Q_UNUSED(resource);
    Q_UNUSED(key);
//    qDebug() << Q_FUNC_INFO << resource << key;
    QTimer::singleShot(100, this, &QWaylandTextureSharingExtension::cleanupBuffers);
}

// A client has disconnected
void QWaylandTextureSharingExtension::zqt_texture_sharing_v1_destroy_resource(Resource *resource)
{
    Q_UNUSED(resource);
//    qDebug() << "texture_sharing_destroy_resource" << resource->handle << resource->handle->object.id << "client" << resource->client();
//    dumpBufferInfo();
    QTimer::singleShot(1000, this, &QWaylandTextureSharingExtension::cleanupBuffers);
}

bool QWaylandTextureSharingExtension::initServerBufferIntegration()
{
    if (!m_server_buffer_integration) {
        QWaylandCompositor *compositor = static_cast<QWaylandCompositor *>(extensionContainer());

        m_server_buffer_integration = QWaylandCompositorPrivate::get(compositor)->serverBufferIntegration();
        if (!m_server_buffer_integration) {
            qWarning("QWaylandTextureSharingExtension initialization failed: No Server Buffer Integration");
            if (qEnvironmentVariableIsEmpty("QT_WAYLAND_SERVER_BUFFER_INTEGRATION"))
                qWarning("Set the environment variable 'QT_WAYLAND_SERVER_BUFFER_INTEGRATION' to specify.");
            return false;
        }
    }
    return true;
}

QtWayland::ServerBuffer *QWaylandTextureSharingExtension::getCompressedBuffer(const QString &pathName)
{
    QFile f(pathName);
    if (!f.open(QIODevice::ReadOnly))
        return nullptr;

    QTextureFileReader r(&f, pathName);

    if (!r.canRead())
        return nullptr;

    QTextureFileData td(r.read());

    //qDebug() << "QWaylandTextureSharingExtension: reading compressed texture data" << td;

    if (!td.isValid()) {
        qWarning() << "VulkanServerBufferIntegration:" << pathName << "not valid compressed texture";
        return nullptr;
    }

    QByteArray pixelData = QByteArray::fromRawData(td.data().constData() + td.dataOffset(), td.dataLength());

    return m_server_buffer_integration->createServerBufferFromData(pixelData, td.size(), td.glInternalFormat());
}

void QWaylandTextureSharingExtension::cleanupBuffers()
{
    for (auto it = m_server_buffers.begin(); it != m_server_buffers.end(); ) {
        auto *buffer = it.value().buffer;
        if (!it.value().usedLocally && !buffer->bufferInUse()) {
            //qDebug() << "deleting buffer for" << it.key();
            it = m_server_buffers.erase(it);
            delete buffer;
        } else {
            ++it;
        }
    }
    //dumpBufferInfo();
}

void QWaylandTextureSharingExtension::dumpBufferInfo()
{
    qDebug() << "shared buffers:" << m_server_buffers.count();
    for (auto it = m_server_buffers.cbegin(); it != m_server_buffers.cend(); ++it)
        qDebug() << "    " << it.key() << ":" << it.value().buffer << "in use" << it.value().buffer->bufferInUse() << "usedLocally" << it.value().usedLocally ;
}

QT_END_NAMESPACE

#include "qwltexturesharingextension.moc"
