// SPDX-FileCopyrightText: Nheko Contributors
//
// SPDX-License-Identifier: GPL-3.0-or-later

#pragma once

#include <QBuffer>
#include <QMovie>
#include <QObject>
#include <QQuickItem>

class TimelineModel;

// This is an AnimatedImage, that can draw encrypted images
class MxcAnimatedImage : public QQuickItem
{
    Q_OBJECT
    QML_ELEMENT
    Q_PROPERTY(TimelineModel *roomm READ room WRITE setRoom NOTIFY roomChanged REQUIRED)
    Q_PROPERTY(QString eventId READ eventId WRITE setEventId NOTIFY eventIdChanged)
    Q_PROPERTY(bool animatable READ animatable NOTIFY animatableChanged)
    Q_PROPERTY(bool loaded READ loaded NOTIFY loadedChanged)
    Q_PROPERTY(bool play READ play WRITE setPlay NOTIFY playChanged)
public:
    MxcAnimatedImage(QQuickItem *parent = nullptr)
      : QQuickItem(parent)
    {
        connect(this, &MxcAnimatedImage::eventIdChanged, &MxcAnimatedImage::startDownload);
        connect(this, &MxcAnimatedImage::roomChanged, &MxcAnimatedImage::startDownload);
        connect(&movie, &QMovie::frameChanged, this, &MxcAnimatedImage::newFrame);
        setFlag(QQuickItem::ItemHasContents);
        setFlag(QQuickItem::ItemObservesViewport);
        // setAcceptHoverEvents(true);
    }

    bool animatable() const { return animatable_; }
    bool loaded() const { return buffer.size() > 0; }
    bool play() const { return play_; }
    QString eventId() const { return eventId_; }
    TimelineModel *room() const { return room_; }
    void setEventId(QString newEventId)
    {
        if (eventId_ != newEventId) {
            eventId_ = newEventId;
            emit eventIdChanged();
        }
    }
    void setRoom(TimelineModel *room)
    {
        if (room_ != room) {
            room_ = room;
            emit roomChanged();
        }
    }
    void setPlay(bool newPlay)
    {
        if (play_ != newPlay) {
            play_ = newPlay;
            if (movie.frameCount() > 1)
                movie.setPaused(!play_);
            else {
                movie.jumpToFrame(0);
                movie.setPaused(true);
            }
            emit playChanged();
        }
    }

    void geometryChange(const QRectF &newGeometry, const QRectF &oldGeometry) override;
    QSGNode *updatePaintNode(QSGNode *oldNode,
                             QQuickItem::UpdatePaintNodeData *updatePaintNodeData) override;

signals:
    void roomChanged();
    void eventIdChanged();
    void animatableChanged();
    void loadedChanged();
    void playChanged();

private slots:
    void startDownload();
    void newFrame(int frame)
    {
        currentFrame = frame;
        imageDirty   = true;
        if (!clipRect().isEmpty())
            update();
    }

private:
    TimelineModel *room_ = nullptr;
    QString eventId_;
    QString filename_;
    bool animatable_ = false;
    QBuffer buffer;
    QMovie movie;
    int currentFrame = 0;
    bool imageDirty  = true;
    bool play_       = true;
};
