/*
 * 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/base/SkAssert.h"
#include "include/private/base/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
}

//////////////////// 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);
    if (uint32_t id = as_IB(image)->getDerivedSurfaceID()) {
        SkRect bounds = SkRect::MakeXYWH(left, top, image->width(), image->height());
        this->drawAnnotation(bounds, "SkCapture_DerivedSurfaceID",
                             SkData::MakeWithCopy(&id, sizeof(id)).get());
        SkContentID contentID = as_IB(image)->getContentID();
        SKIA_LOG_D("SkCaptureCanvas::onDrawImage2: DerivedSurfaceID=%u, ContentID=%u\n",
                   id, contentID.asUInt());
        if (contentID) {
            this->drawAnnotation(bounds, "SkCapture_ContentID",
                                 SkData::MakeWithCopy(&contentID, sizeof(contentID)).get());
        }
    }
}

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);
    if (uint32_t id = as_IB(image)->getDerivedSurfaceID()) {
        this->drawAnnotation(dst, "SkCapture_DerivedSurfaceID",
                             SkData::MakeWithCopy(&id, sizeof(id)).get());
        SkContentID contentID = as_IB(image)->getContentID();
        SKIA_LOG_D("SkCaptureCanvas::onDrawImageRect2: DerivedSurfaceID=%u, ContentID=%u\n",
                   id, contentID.asUInt());
        if (contentID) {
            this->drawAnnotation(dst, "SkCapture_ContentID",
                                 SkData::MakeWithCopy(&contentID, sizeof(contentID)).get());
        }
    }
}

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);
    if (uint32_t id = as_IB(image)->getDerivedSurfaceID()) {
        this->drawAnnotation(dst, "SkCapture_DerivedSurfaceID",
                             SkData::MakeWithCopy(&id, sizeof(id)).get());
        SkContentID contentID = as_IB(image)->getContentID();
        SKIA_LOG_D("SkCaptureCanvas::onDrawImageLattice2: DerivedSurfaceID=%u, ContentID=%u\n",
                   id, contentID.asUInt());
        if (contentID) {
            this->drawAnnotation(dst, "SkCapture_ContentID",
                                 SkData::MakeWithCopy(&contentID, sizeof(contentID)).get());
        }
    }
}

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);
    if (uint32_t id = as_IB(image)->getDerivedSurfaceID()) {
        SkRect bounds = cull ? *cull : SkRect::MakeEmpty();
        this->drawAnnotation(bounds, "SkCapture_DerivedSurfaceID",
                             SkData::MakeWithCopy(&id, sizeof(id)).get());
        SkContentID contentID = as_IB(image)->getContentID();
        SKIA_LOG_D("SkCaptureCanvas::onDrawAtlas2: DerivedSurfaceID=%u, ContentID=%u\n",
                   id, contentID.asUInt());
        if (contentID) {
            this->drawAnnotation(bounds, "SkCapture_ContentID",
                                 SkData::MakeWithCopy(&contentID, sizeof(contentID)).get());
        }
    }
}

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);
    for (int i = 0; i < count; ++i) {
        if (uint32_t id = as_IB(set[i].fImage.get())->getDerivedSurfaceID()) {
            this->drawAnnotation(set[i].fDstRect, "SkCapture_DerivedSurfaceID",
                                 SkData::MakeWithCopy(&id, sizeof(id)).get());
            SkContentID contentID = as_IB(set[i].fImage.get())->getContentID();
            SKIA_LOG_D("SkCaptureCanvas::onDrawEdgeAAImageSet[%d]: DerivedSurface=%u, Content=%u\n",
                       i, id, contentID.asUInt());
            if (contentID) {
                this->drawAnnotation(set[i].fDstRect, "SkCapture_ContentID",
                                     SkData::MakeWithCopy(&contentID, sizeof(contentID)).get());
            }
        }
    }
}

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