/*
 * Copyright 2024 Google LLC
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */
#ifndef SkPngRustCodec_DEFINED
#define SkPngRustCodec_DEFINED

#include <memory>
#include <variant>
#include <vector>

#include "include/core/SkSpan.h"
#include "rust/png/FFI.rs.h"
#include "src/codec/SkCodecPriv.h"
#include "src/codec/SkFrameHolder.h"
#include "src/codec/SkPngCodecBase.h"
#include "third_party/rust/cxx/v1/cxx.h"

class SkFrame;
class SkStream;
struct SkEncodedInfo;

// This class provides the Skia image decoding API (`SkCodec`) on top of:
// * The third-party `png` crate (PNG decompression and decoding implemented in
//   Rust)
// * Skia's `SkSwizzler` and `skcms_Transform` (pixel format and color space
//   transformations implemented in C++).
class SkPngRustCodec final : public SkPngCodecBase {
public:
    static std::unique_ptr<SkPngRustCodec> MakeFromStream(std::unique_ptr<SkStream>,
                                                          Result*,
                                                          SkPngChunkReader* = nullptr);

    // `public` to support `std::make_unique<SkPngRustCodec>(...)`.
    SkPngRustCodec(SkEncodedInfo&&,
                   std::unique_ptr<SkStream>,
                   rust::Box<rust_png::Reader>,
                   sk_sp<SkPngCompositeChunkReader>,
                   std::unique_ptr<SkStream> gainmapStream,
                   std::optional<SkGainmapInfo> gainmapInfo);

    ~SkPngRustCodec() override;

private:
    // Holds raw destination parameters captured in `startDecoding` before
    // sampler/swizzler options are finalized.
    struct UninitializedDstInfo {
        // Pointer to the start of the caller's destination pixel buffer.
        uint8_t* fDstPtr;

        // Size of a row (in bytes) in the full image. Based on `rowBytes`
        // passed to `onGetPixels` or `onStartIncrementalDecode`.
        size_t fDstRowStride;
    };

    // Holds validated and calculated destination spans after `initializeDecodingDst`
    // has run.
    struct DecodingDstInfo {
        // Size of a row (in bytes) in the full image.
        size_t fDstRowStride;

        // `fDst` is based on `fDstPtr` from `UninitializedDstInfo`. For interlaced
        // and non-interlaced images, `initializeDecodingDst` initializes `fDst`
        // to start at the (0,0) (top-left) pixel of the current frame (which may
        // be offset from `fDstPtr` if the current frame is a sub-rect of the full
        // image). After decoding a non-interlaced row this moves (by
        // `fDstRowStride`) to the next row.
        SkSpan<uint8_t> fDst;

        // Size of a row (in bytes) in the current frame (or subset/sampled output).
        size_t fDstRowSize;

        // Height (in rows) of the current frame (or subset/sampled output).
        int fDstRowCount;

        // Bytes per pixel of fDst.
        uint8_t fDstBytesPerPixel;
    };

    struct DecodingState {
        // Transitions from `UninitializedDstInfo` (set in `startDecoding`) ->
        // `DecodingDstInfo` (populated by `initializeDecodingDst` once sampling
        // and swizzler parameters are finalized).
        std::variant<UninitializedDstInfo, DecodingDstInfo> fDst;

        DecodingDstInfo& dst() { return std::get<DecodingDstInfo>(fDst); }

        // Intermediate buffer that holds color-transformed pixels that are
        // ready to be blended with the destination. Used only when this frame
        // uses `SkCodecAnimation::Blend::kSrcOver`. For interlaced images this
        // buffer holds the whole frame; otherwise it holds only a single row.
        //
        // This is also used in the case of subsets or sampling for interlaced
        // images. We use this buffer as a full sized encoded image, which we then
        // take the subset / sampled rows from.
        // TODO: Subsets of APNG not supported, but if we need to, we would need
        // a separate fInterlacedBuffer along with fPreblendBuffer.
        SkCodecPriv::BudgetedBuffer fPreblendBuffer;

        // Single-row scratch buffers used when decoding interlaced images (unless
        // decoding a subset or sampling, where the whole untransformed image is
        // decoded into `fPreblendBuffer` first):
        // * `fDecodedInterlacedFullWidthRow` (size `getEncodedRowBytes()`): holds
        //   the decoded interlaced row padded to full width (used by `read_row` in
        //   `incrementalDecode`, or to pad `srcRow` for `applyXformRow` in
        //   `expandDecodedInterlacedRow`).
        // * `fXformedInterlacedRow` (size `fDstRowSize`): holds the color-transformed
        //   interlaced row in `expandDecodedInterlacedRow` when `!canReadRow()`.
        SkCodecPriv::BudgetedBuffer fDecodedInterlacedFullWidthRow;
        SkCodecPriv::BudgetedBuffer fXformedInterlacedRow;

        int fFirstRow = 0;
        int fLastRow = 0;

        // Tracks the current row index of the source image being processed.
        // Needs to be persisted in DecodingState to support incremental decoding
        // across multiple calls without resetting progress.
        int fCurrentSourceRow = 0;
        // Number of destination rows written to `fDst` so far:
        // * Non-interlaced: incremented after each decoded row.
        // * Interlaced full-image: updated in `expandDecodedInterlacedRow` from
        //   `fInterlacedDecodedHeight`.
        // * Interlaced subset/sampled: updated when flushing `fPreblendBuffer` in
        //   `writeSubsetOrSampleToOutput`.
        int fRowsWrittenToOutput = 0;

        // The y offset for a subset in the encoded color type, not the dst color type.
        // Only used for interlaced images.
        size_t fYByteOffset = 0;

        // Height (in rows) initialized so far by `splat_last_interlaced_row` (+8
        // rows per Pass 1 scanline).
        int fInterlacedDecodedHeight = 0;
    };

    // Helper for validating parameters of `onGetPixels` and/or
    // `onStartIncrementalDecode`. If `kSuccess` is returned then
    // `decodingState` output parameter got populated.
    Result startDecoding(const SkImageInfo& dstInfo,
                         void* pixels,
                         size_t rowBytes,
                         const Options& options,
                         std::optional<DecodingState>& decodingState);

    // Helper for initializing the destination span (`fDst`), row size, and
    // preblend buffer once sampling/subsetting parameters are finalized.
    Result initializeDecodingDst(DecodingState& decodingState);

    // Helper for taking a decoded interlaced `srcRow`, applying color
    // transformations, and then expanding it into the `frame`.
    void expandDecodedInterlacedRow(DecodingState& decodingState,
                                    SkSpan<uint8_t> dstFrame,
                                    SkSpan<const uint8_t> srcRow,
                                    const DecodingDstInfo& decodingDst,
                                    bool xFormNeeded);

    // Helper for row-by-row decoding which is used from `onGetPixels` and/or
    // `onIncrementalDecode`.
    Result incrementalDecode(DecodingState& decodingState);
    // The same as incrementalDecode but uses `applyXFormRow()`. Should only
    // be used if this->canReadRows() is false.
    Result incrementalDecodeXForm(DecodingState& decodingState);

    // Extracts and/or samples the rows decoded so far in `fPreblendBuffer` (in
    // the encoded color type) into `fDst` using `applyXformRow()`, and records
    // the number of destination rows written in `fRowsWrittenToOutput`. Used
    // for interlaced subset/sampled decodes both on halt and at end-of-frame.
    void writeSubsetOrSampleToOutput(DecodingState& decodingState);

    // Populates `rowsDecoded` after a failed decode (`kIncompleteInput` or
    // `kErrorInInput`) with the number of destination rows written so far,
    // matching `SkPngCodec` so callers only fill the remaining rows.
    void reportRowsDecoded(Result result,
                           const DecodingState& decodingState,
                           int* rowsDecoded) const;

    // Helper for reading until the start of the next `fdAT` sequence.
    Result readToStartOfNextFrame();

    // Helper for seeking to the start of image data for the given frame.
    Result seekToStartOfFrame(int index);

    // The number of frames calculated based on 1) the presence, and 2) the
    // contents of an `acTL` chunk.  "raw" in the sense that it reports all the
    // frames, while `SkCodec::getFrameCount` and
    // `SkPngRustCodec::onGetFrameCount` only report frames for which we have
    // successfully populated `fFrameHolder` with frame info parsed from `IHDR`
    // and/or `fcTL` chunks.
    int getRawFrameCount() const;

    // Attempts to read through the input stream to parse the additional `fcTL`
    // chunks.
    Result parseAdditionalFrameInfos();

    // Determines whether or not we can read from the rust decoder directly into dst.
    bool canReadRow();
    void processUnknownChunks();
    bool isLastFrame();
    bool isSampling() const;
    // Helper to query whether the image supports sampling or subsetting
    // (only static full-canvas images are supported; APNG animations and
    // offset frames are unsupported).
    bool supportsSamplingOrSubsetting();
    // Leaves the stream just past `IEND` so that callers can keep reading it (see `Codec_end`).
    // Like libpng, partial decodes skip this and stop early. Errors are ignored: the scanlines and
    // the `IDAT` CRC are verified already, and libpng also tolerates a damaged tail (it checks the
    // `IEND` CRC as if it were ancillary). No-op unless the codec is built `for_android`.
    void finishStreamAfterLastFrame();

    // SkCodec overrides:
    Result onGetPixels(const SkImageInfo& dstInfo,
                       void* pixels,
                       size_t rowBytes,
                       const Options&,
                       int* rowsDecoded) override;
    bool onSupportsIncrementalDecode(const SkImageInfo&) override { return true; }
    Result onStartIncrementalDecode(const SkImageInfo& dstInfo,
                                    void* pixels,
                                    size_t rowBytes,
                                    const Options&) override;
    Result onIncrementalDecode(int* rowsDecoded) override;
    int onGetFrameCount() override;
    bool onGetFrameInfo(int, FrameInfo*) const override;
    int onGetRepetitionCount() override;
    IsAnimated onIsAnimated() override;
    const SkFrameHolder* getFrameHolder() const override;
    sk_sp<const SkData> getEncodedData() const override;
    SkSampler* getSampler(bool createIfNecessary) final;

    // SkPngCodecBase overrides:
    std::unique_ptr<SkCodec> onDecodeGainmap(std::unique_ptr<SkStream> stream,
                                             SkCodec::Result* result) override;
    std::optional<SkSpan<const PaletteColorEntry>> onTryGetPlteChunk() override;
    std::optional<SkSpan<const uint8_t>> onTryGetTrnsChunk() override;

    rust::Box<rust_png::Reader> fReader;

    // `-1` means that `IDAT` is not part of animation and wasn't skipped yet.
    int fFrameAtCurrentStreamPosition = -1;
    bool fStreamIsPositionedAtStartOfFrameData = false;
    const std::unique_ptr<SkStream> fPrivStream;
    // TODO(https://crbug.com/371060427): Once fast seeking is available, we can
    // remove the field that tracks the stream length.
    std::optional<size_t> fMaxStreamLengthSeenWhenParsingAdditionalFrameInfos;

    std::optional<DecodingState> fIncrementalDecodingState;

    class FrameHolder final : public SkFrameHolder {
    public:
        FrameHolder(int width, int height);
        ~FrameHolder() override;

        FrameHolder(const FrameHolder&) = delete;
        FrameHolder(FrameHolder&&) = delete;
        FrameHolder& operator=(const FrameHolder&) = delete;
        FrameHolder& operator=(FrameHolder&&) = delete;

        // Returning an `int` (rather than `size_t`) for easier interop with
        // other parts of the SkCodec API.
        int size() const;

        Result appendNewFrame(const rust_png::Reader& reader, const SkEncodedInfo& info);
        void markFrameAsFullyReceived(size_t index);
        bool getFrameInfo(int index, FrameInfo* info) const;

    private:
        class PngFrame;

        const SkFrame* onGetFrame(int unverifiedIndex) const override;
        Result setFrameInfoFromCurrentFctlChunk(const rust_png::Reader& reader,
                                                PngFrame* out_frame);

        std::vector<PngFrame> fFrames;
    };
    FrameHolder fFrameHolder;

    // Whether there may still be additional `fcTL` chunks to discover and parse.
    //
    // `true` if the stream hasn't been fully received (i.e. only
    // `kIncompleteInput` errors so far, no hard errors) and `fFrameHolder`
    // doesn't yet contain frame info for all `num_frames` declared in an `acTL`
    // chunk.
    bool fCanParseAdditionalFrameInfos = true;
};

#endif  // SkPngRustCodec_DEFINED
