/*
    SPDX-FileCopyrightText: 2011 Martin Gräßlin <mgraesslin@kde.org>
    SPDX-FileCopyrightText: 2021 Vlad Zahorodnii <vlad.zahorodnii@kde.org>

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

#pragma once

#include <QQuickItem>
#include <QUuid>

#include <epoxy/gl.h>

namespace KWin
{

class Window;
class GLFramebuffer;
class GLTexture;
class ThumbnailTextureProvider;
class WindowThumbnailSource;

class WindowThumbnailSource : public QObject
{
    Q_OBJECT

public:
    WindowThumbnailSource(QQuickWindow *view, Window *handle);
    ~WindowThumbnailSource() override;

    static std::shared_ptr<WindowThumbnailSource> getOrCreate(QQuickWindow *window, Window *handle);

    struct Frame
    {
        std::shared_ptr<GLTexture> texture;
        GLsync fence;
    };

    Frame acquire();

Q_SIGNALS:
    void changed();

private:
    void update();

    QPointer<QQuickWindow> m_view;
    QPointer<Window> m_handle;

    std::shared_ptr<GLTexture> m_offscreenTexture;
    std::unique_ptr<GLFramebuffer> m_offscreenTarget;
    GLsync m_acquireFence = 0;
    bool m_dirty = true;
};

/*!
 * \qmltype WindowThumbnail
 * \inqmlmodule org.kde.kwin
 * \inherits Item
 *
 * \brief Window Thumbnail.
 */
class WindowThumbnailItem : public QQuickItem
{
    Q_OBJECT
    /*!
     * \qmlproperty QUuid WindowThumbnail::wId
     */
    Q_PROPERTY(QUuid wId READ wId WRITE setWId NOTIFY wIdChanged)

    /*!
     * \qmlproperty Window WindowThumbnail::client
     */
    Q_PROPERTY(KWin::Window *client READ client WRITE setClient NOTIFY clientChanged)

public:
    explicit WindowThumbnailItem(QQuickItem *parent = nullptr);
    ~WindowThumbnailItem() override;

    QUuid wId() const;
    void setWId(const QUuid &wId);

    Window *client() const;
    void setClient(Window *client);

    QSGTextureProvider *textureProvider() const override;
    bool isTextureProvider() const override;
    QSGNode *updatePaintNode(QSGNode *oldNode, QQuickItem::UpdatePaintNodeData *) override;

protected:
    void releaseResources() override;
    void itemChange(QQuickItem::ItemChange change, const QQuickItem::ItemChangeData &value) override;

Q_SIGNALS:
    void wIdChanged();
    void clientChanged();

private Q_SLOTS:
    /**
     * @brief Releases graphics resources of this object.
     *
     * This slot is called on the scene graph rendering thread to free graphics
     * resources associated with this object, typically when QQuickWindow is closed
     * or hidden. The OpenGL context is bound when this slot is called.
     *
     * @note Do not remove this slot. It is called directly by the scene graph
     * system via Qt's meta-object mechanism, not through signal-slot connections.
     */
    void invalidateSceneGraph();

private:
    QRectF paintedRect() const;
    void updateImplicitSize();
    void updateSource();
    void resetSource();

    QUuid m_wId;
    QPointer<Window> m_client;

    mutable ThumbnailTextureProvider *m_provider = nullptr;
    std::shared_ptr<WindowThumbnailSource> m_source;
};

} // namespace KWin
