/*
 * Copyright 2017 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#ifndef SkFrameHolder_DEFINED
#define SkFrameHolder_DEFINED

#include "include/codec/SkCodecAnimation.h"
#include "include/core/SkRect.h"
#include "include/core/SkTypes.h"
#include "src/codec/SkCodecAnimationPriv.h"

/**
 *  Base class for a single frame of an animated image.
 *
 *  Separate from SkCodec::FrameInfo, which is a pared down
 *  interface that only contains the info the client needs.
 */
class SkFrame : public SkNoncopyable {
public:
    SkFrame(int id)
        : fId(id)
        , fHasAlpha(false)
        , fRequiredFrame(kUninitialized)
        , fDisposalMethod(SkCodecAnimation::DisposalMethod::kKeep)
        , fDuration(0)
        , fBlend(SkCodecAnimation::Blend::kPriorFrame)
    {
        fRect.setEmpty();
    }

    virtual ~SkFrame() {}

    /**
     * An explicit move constructor, as
     * https://en.cppreference.com/w/cpp/language/move_constructor says that
     * there is no implicit move constructor if there are user-declared
     * destructors, and we have one, immediately above.
     *
     * Without a move constructor, it is harder to use an SkFrame, or an
     * SkFrame subclass, inside a std::vector.
     */
    SkFrame(SkFrame&&) = default;

    /**
     *  0-based index of the frame in the image sequence.
     */
    int frameId() const { return fId; }

    /**
     *  How this frame reports its alpha.
     *
     *  This only considers the rectangle of this frame, and
     *  considers it to have alpha even if it is opaque once
     *  blended with the frame behind it.
     */
    SkEncodedInfo::Alpha reportedAlpha() const {
        return this->onReportedAlpha();
    }

    /**
     *  Cached value representing whether the frame has alpha,
     *  after compositing with the prior frame.
     */
    bool hasAlpha() const { return fHasAlpha; }

    /**
     *  Cache whether the finished frame has alpha.
     */
    void setHasAlpha(bool alpha) { fHasAlpha = alpha; }

    /**
     *  Whether enough of the frame has been read to determine
     *  fRequiredFrame and fHasAlpha.
     */
    bool reachedStartOfData() const { return fRequiredFrame != kUninitialized; }

    /**
     *  The frame this one depends on.
     *
     *  Must not be called until fRequiredFrame has been set properly.
     */
    int getRequiredFrame() const {
        SkASSERT(this->reachedStartOfData());
        return fRequiredFrame;
    }

    /**
     *  Set the frame that this frame depends on.
     */
    void setRequiredFrame(int req) { fRequiredFrame = req; }

    /**
     *  Set the rectangle that is updated by this frame.
     */
    void setXYWH(int x, int y, int width, int height) {
        fRect.setXYWH(x, y, width, height);
    }

    /**
     *  The rectangle that is updated by this frame.
     */
    SkIRect frameRect() const { return fRect; }

    int xOffset() const { return fRect.x(); }
    int yOffset() const { return fRect.y(); }
    int width()   const { return fRect.width(); }
    int height()  const { return fRect.height(); }

    SkCodecAnimation::DisposalMethod getDisposalMethod() const {
        return fDisposalMethod;
    }

    void setDisposalMethod(SkCodecAnimation::DisposalMethod disposalMethod) {
        fDisposalMethod = disposalMethod;
    }

    /**
     * Set the duration (in ms) to show this frame.
     */
    void setDuration(int duration) {
        fDuration = duration;
    }

    /**
     *  Duration in ms to show this frame.
     */
    int getDuration() const {
        return fDuration;
    }

    void setBlend(SkCodecAnimation::Blend blend) {
        fBlend = blend;
    }

    SkCodecAnimation::Blend getBlend() const {
        return fBlend;
    }

protected:
    virtual SkEncodedInfo::Alpha onReportedAlpha() const = 0;

private:
    static constexpr int kUninitialized = -2;

    const int                           fId;
    bool                                fHasAlpha;
    int                                 fRequiredFrame;
    SkIRect                             fRect;
    SkCodecAnimation::DisposalMethod    fDisposalMethod;
    int                                 fDuration;
    SkCodecAnimation::Blend             fBlend;
};

/**
 *  Base class for an object which holds the SkFrames of an
 *  image sequence.
 */
class SkFrameHolder : public SkNoncopyable {
public:
    SkFrameHolder()
        : fScreenWidth(0)
        , fScreenHeight(0)
    {}

    virtual ~SkFrameHolder() {}

    /**
     *  Size of the image. Each frame will be contained in
     *  these dimensions (possibly after clipping).
     */
    int screenWidth() const { return fScreenWidth; }
    int screenHeight() const { return fScreenHeight; }

    /**
     *  Compute the opacity and required frame, based on
     *  the frame's reportedAlpha and how it blends
     *  with prior frames.
     */
    void setAlphaAndRequiredFrame(SkFrame*);

    /**
     *  Return the frame with frameId i.
     */
    const SkFrame* getFrame(int i) const {
        return this->onGetFrame(i);
    }

protected:
    int fScreenWidth;
    int fScreenHeight;

    virtual const SkFrame* onGetFrame(int i) const = 0;
};

#endif // SkFrameHolder_DEFINED
