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

#include "src/capture/SkCaptureCanvas.h"

#include "include/core/SkPicture.h"
#include "include/core/SkRasterHandleAllocator.h"
#include "include/core/SkRefCnt.h"
#include "include/core/SkSurface.h"
#include "include/private/SkAssert.h"
#include "include/private/SkLog.h"
#include "include/utils/SkNWayCanvas.h"
#include "src/capture/SkCaptureManager.h"
#include "src/core/SkCanvasPriv.h"
#include "src/image/SkImage_Base.h"

SkCaptureCanvas::SkCaptureCanvas(SkCanvas* canvas, SkCaptureManager* manager)
        : SkNWayCanvas(canvas->imageInfo().width(), canvas->imageInfo().height()) {
    fBaseCanvas = canvas;
    fManager = manager;
    this->addCanvas(canvas);
}

SkCaptureCanvas::~SkCaptureCanvas() = default;

void SkCaptureCanvas::pollCapturingStatus() {
    bool shouldPoll = fManager->isCurrentlyCapturing();
    if (fCapturing != shouldPoll) {
        if (shouldPoll) {
            this->attachRecordingCanvas();
        } else {
            this->detachRecordingCanvas();
        }
        fCapturing = shouldPoll;
    }
}

sk_sp<SkPicture> SkCaptureCanvas::snapPicture() {
    if (!fCapturing) {
        return nullptr;
    }
    this->detachRecordingCanvas(); // remove the stale recording canvas before the recorder finishes
    auto skp = fRecorder.finishRecordingAsPicture();
    this->attachRecordingCanvas();
    return skp;
}

void SkCaptureCanvas::attachRecordingCanvas() {
    SkASSERT(this->fList.size() == 1);
    this->addCanvas(fRecorder.beginRecording(fBaseCanvas->imageInfo().width(),
                                              fBaseCanvas->imageInfo().height()));
}

void SkCaptureCanvas::detachRecordingCanvas() {
    SkASSERT(this->fList.size() == 2);
    this->removeCanvas(fRecorder.getRecordingCanvas());
}

void SkCaptureCanvas::onSurfaceDelete() {
    // TODO (b/412351769): signal to the capture manager that this canvas's surface has been deleted
}

SkSurface_Base* SkCaptureCanvas::getSurfaceBase() const {
    return this->fBaseCanvas->getSurfaceBase();
}

//////////////////// Function forwarding ///////////////////////

void SkCaptureCanvas::willSave() {
    this->pollCapturingStatus();
    this->SkNWayCanvas::willSave();
}

SkCanvas::SaveLayerStrategy SkCaptureCanvas::getSaveLayerStrategy(const SaveLayerRec& rec) {
    this->pollCapturingStatus();
    return this->SkNWayCanvas::getSaveLayerStrategy(rec);
}

bool SkCaptureCanvas::onDoSaveBehind(const SkRect* bounds) {
    this->pollCapturingStatus();
    return this->SkNWayCanvas::onDoSaveBehind(bounds);
}

void SkCaptureCanvas::willRestore() {
    this->pollCapturingStatus();
    this->SkNWayCanvas::willRestore();
}

void SkCaptureCanvas::didConcat44(const SkM44& m) {
    this->pollCapturingStatus();
    this->SkNWayCanvas::didConcat44(m);
}

void SkCaptureCanvas::didSetM44(const SkM44& matrix) {
    this->pollCapturingStatus();
    this->SkNWayCanvas::didSetM44(matrix);
}

void SkCaptureCanvas::didTranslate(SkScalar x, SkScalar y) {
    this->pollCapturingStatus();
    this->SkNWayCanvas::didTranslate(x, y);
}

void SkCaptureCanvas::didScale(SkScalar x, SkScalar y) {
    this->pollCapturingStatus();
    this->SkNWayCanvas::didScale(x, y);
}

void SkCaptureCanvas::onClipRect(const SkRect& rect, SkClipOp op, ClipEdgeStyle edgeStyle) {
    this->pollCapturingStatus();
    this->SkNWayCanvas::onClipRect(rect, op, edgeStyle);
}

void SkCaptureCanvas::onClipRRect(const SkRRect& rrect, SkClipOp op, ClipEdgeStyle edgeStyle) {
    this->pollCapturingStatus();
    this->SkNWayCanvas::onClipRRect(rrect, op, edgeStyle);
}

void SkCaptureCanvas::onClipPath(const SkPath& path, SkClipOp op, ClipEdgeStyle edgeStyle) {
    this->pollCapturingStatus();
    this->SkNWayCanvas::onClipPath(path, op, edgeStyle);
}

void SkCaptureCanvas::onClipShader(sk_sp<SkShader> sh, SkClipOp op) {
    this->pollCapturingStatus();
    this->SkNWayCanvas::onClipShader(sh, op);
}

void SkCaptureCanvas::onClipRegion(const SkRegion& deviceRgn, SkClipOp op) {
    this->pollCapturingStatus();
    this->SkNWayCanvas::onClipRegion(deviceRgn, op);
}

void SkCaptureCanvas::onResetClip() {
    this->pollCapturingStatus();
    this->SkNWayCanvas::onResetClip();
}

void SkCaptureCanvas::onDrawPaint(const SkPaint& paint) {
    this->pollCapturingStatus();
    this->SkNWayCanvas::onDrawPaint(paint);
}

void SkCaptureCanvas::onDrawBehind(const SkPaint& paint) {
    this->pollCapturingStatus();
    this->SkNWayCanvas::onDrawBehind(paint);
}

void SkCaptureCanvas::onDrawPoints(PointMode mode,
                                   size_t count,
                                   const SkPoint pts[],
                                   const SkPaint& paint) {
    this->pollCapturingStatus();
    this->SkNWayCanvas::onDrawPoints(mode, count, pts, paint);
}

void SkCaptureCanvas::onDrawRect(const SkRect& rect, const SkPaint& paint) {
    this->pollCapturingStatus();
    this->SkNWayCanvas::onDrawRect(rect, paint);
}

void SkCaptureCanvas::onDrawRegion(const SkRegion& region, const SkPaint& paint) {
    this->pollCapturingStatus();
    this->SkNWayCanvas::onDrawRegion(region, paint);
}

void SkCaptureCanvas::onDrawOval(const SkRect& rect, const SkPaint& paint) {
    this->pollCapturingStatus();
    this->SkNWayCanvas::onDrawOval(rect, paint);
}

void SkCaptureCanvas::onDrawArc(const SkRect& rect,
                                SkScalar startAngle,
                                SkScalar sweepAngle,
                                bool useCenter,
                                const SkPaint& paint) {
    this->pollCapturingStatus();
    this->SkNWayCanvas::onDrawArc(rect, startAngle, sweepAngle, useCenter, paint);
}

void SkCaptureCanvas::onDrawRRect(const SkRRect& rrect, const SkPaint& paint) {
    this->pollCapturingStatus();
    this->SkNWayCanvas::onDrawRRect(rrect, paint);
}

void SkCaptureCanvas::onDrawDRRect(const SkRRect& outer,
                                   const SkRRect& inner,
                                   const SkPaint& paint) {
    this->pollCapturingStatus();
    this->SkNWayCanvas::onDrawDRRect(outer, inner, paint);
}

void SkCaptureCanvas::onDrawPath(const SkPath& path, const SkPaint& paint) {
    this->pollCapturingStatus();
    this->SkNWayCanvas::onDrawPath(path, paint);
}

void SkCaptureCanvas::onDrawImage2(const SkImage* image,
                                   SkScalar left,
                                   SkScalar top,
                                   const SkSamplingOptions& sampling,
                                   const SkPaint* paint) {
    this->pollCapturingStatus();
    this->SkNWayCanvas::onDrawImage2(image, left, top, sampling, paint);
    for (const auto& storage : as_IB(image)->getPixelStorages()) {
        if (storage) {
            // TODO (b/412351769): Track image metadata in the capture manager.
            SKIA_LOG_D("SkCaptureCanvas::onDrawImage2: StorageID=%u, ContentID=%u\n",
                     storage->getPixelStorageId(), storage->getContentId());
        }
    }
}

void SkCaptureCanvas::onDrawImageRect2(const SkImage* image,
                                       const SkRect& src,
                                       const SkRect& dst,
                                       const SkSamplingOptions& sampling,
                                       const SkPaint* paint,
                                       SrcRectConstraint constraint) {
    this->pollCapturingStatus();
    this->SkNWayCanvas::onDrawImageRect2(image, src, dst, sampling, paint, constraint);
    for (const auto& storage : as_IB(image)->getPixelStorages()) {
        if (storage) {
            // TODO (b/412351769): Track image metadata in the capture manager.
            SKIA_LOG_D("SkCaptureCanvas::onDrawImageRect2: StorageID=%u, ContentID=%u\n",
                     storage->getPixelStorageId(), storage->getContentId());
        }
    }
}

void SkCaptureCanvas::onDrawImageLattice2(const SkImage* image,
                                          const Lattice& lattice,
                                          const SkRect& dst,
                                          SkFilterMode filter,
                                          const SkPaint* paint) {
    this->pollCapturingStatus();
    this->SkNWayCanvas::onDrawImageLattice2(image, lattice, dst, filter, paint);
    for (const auto& storage : as_IB(image)->getPixelStorages()) {
        if (storage) {
            // TODO (b/412351769): Track image metadata in the capture manager.
            SKIA_LOG_D("SkCaptureCanvas::onDrawImageLattice2: StorageID=%u, ContentID=%u\n",
                     storage->getPixelStorageId(), storage->getContentId());
        }
    }
}

void SkCaptureCanvas::onDrawAtlas2(const SkImage* image,
                                   const SkRSXform xform[],
                                   const SkRect tex[],
                                   const SkColor colors[],
                                   int count,
                                   SkBlendMode bmode,
                                   const SkSamplingOptions& sampling,
                                   const SkRect* cull,
                                   const SkPaint* paint) {
    this->pollCapturingStatus();
    this->SkNWayCanvas::onDrawAtlas2(image, xform, tex, colors, count, bmode, sampling, cull, paint);
    for (const auto& storage : as_IB(image)->getPixelStorages()) {
        if (storage) {
            // TODO (b/412351769): Track image metadata in the capture manager.
            SKIA_LOG_D("SkCaptureCanvas::onDrawAtlas2: StorageID=%u, ContentID=%u\n",
                     storage->getPixelStorageId(), storage->getContentId());
        }
    }
}

void SkCaptureCanvas::onDrawGlyphRunList(const sktext::GlyphRunList& list, const SkPaint& paint) {
    this->pollCapturingStatus();
    this->SkNWayCanvas::onDrawGlyphRunList(list, paint);
}

void SkCaptureCanvas::onDrawTextBlob(const SkTextBlob* blob,
                                     SkScalar x,
                                     SkScalar y,
                                     const SkPaint& paint) {
    this->pollCapturingStatus();
    this->SkNWayCanvas::onDrawTextBlob(blob, x, y, paint);
}

void SkCaptureCanvas::onDrawSlug(const sktext::gpu::Slug* slug, const SkPaint& paint) {
    this->pollCapturingStatus();
    this->SkNWayCanvas::onDrawSlug(slug, paint);
}

void SkCaptureCanvas::onDrawPicture(const SkPicture* picture,
                                    const SkMatrix* matrix,
                                    const SkPaint* paint) {
    this->pollCapturingStatus();
    this->SkNWayCanvas::onDrawPicture(picture, matrix, paint);
}

void SkCaptureCanvas::onDrawDrawable(SkDrawable* drawable, const SkMatrix* matrix) {
    this->pollCapturingStatus();
    this->SkNWayCanvas::onDrawDrawable(drawable, matrix);
}

void SkCaptureCanvas::onDrawVerticesObject(const SkVertices* vertices,
                                           SkBlendMode bmode,
                                           const SkPaint& paint) {
    this->pollCapturingStatus();
    this->SkNWayCanvas::onDrawVerticesObject(vertices, bmode, paint);
}

void SkCaptureCanvas::onDrawPatch(const SkPoint cubics[12],
                                  const SkColor colors[4],
                                  const SkPoint texCoords[4],
                                  SkBlendMode bmode,
                                  const SkPaint& paint) {
    this->pollCapturingStatus();
    this->SkNWayCanvas::onDrawPatch(cubics, colors, texCoords, bmode, paint);
}

void SkCaptureCanvas::onDrawShadowRec(const SkPath& path, const SkDrawShadowRec& rec) {
    this->pollCapturingStatus();
    this->SkNWayCanvas::onDrawShadowRec(path, rec);
}

void SkCaptureCanvas::onDrawAnnotation(const SkRect& rect, const char key[], SkData* data) {
    this->pollCapturingStatus();
    this->SkNWayCanvas::onDrawAnnotation(rect, key, data);
}

void SkCaptureCanvas::onDrawEdgeAAQuad(const SkRect& rect,
                                       const SkPoint clip[4],
                                       QuadAAFlags aa,
                                       const SkColor4f& color,
                                       SkBlendMode mode) {
    this->pollCapturingStatus();
    this->SkNWayCanvas::onDrawEdgeAAQuad(rect, clip, aa, color, mode);
}

void SkCaptureCanvas::onDrawEdgeAAImageSet2(const ImageSetEntry set[],
                                            int count,
                                            const SkPoint dstClips[],
                                            const SkMatrix preViewMatrices[],
                                            const SkSamplingOptions& sampling,
                                            const SkPaint* paint,
                                            SrcRectConstraint constraint) {
    this->pollCapturingStatus();
    this->SkNWayCanvas::onDrawEdgeAAImageSet2(
            set, count, dstClips, preViewMatrices, sampling, paint, constraint);
}

SkSurface* SkCaptureCanvas::getBaseCanvasSurface() const {
    return fBaseCanvas->getSurface();
}
