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

#include "gm/gm.h"

#include "include/core/SkCanvas.h"
#include "include/core/SkSurface.h"
#include "include/effects/SkGradient.h"
#include "tools/DecodeUtils.h"
#include "tools/Resources.h"
#include "tools/ToolUtils.h"

#if defined(SK_GRAPHITE)
#include "include/gpu/graphite/Context.h"
#include "include/gpu/graphite/Recorder.h"
#include "include/gpu/graphite/Recording.h"
#include "include/gpu/graphite/TextureInfo.h"
#include "src/gpu/graphite/RecorderPriv.h"
#include "src/gpu/graphite/Surface_Graphite.h"
#include "tools/graphite/GraphiteToolUtils.h"
#endif

namespace skiagm {

class GraphiteReplayGM : public GM {
public:
    GraphiteReplayGM() = default;

protected:
    void onOnceBeforeDraw() override {
        this->setBGColor(SK_ColorBLACK);
        fImage = ToolUtils::GetResourceAsImage("images/mandrill_128.png");
    }

    SkString getName() const override { return SkString("graphite-replay"); }

    SkISize getISize() override { return SkISize::Make(kTileWidth * 3, kTileHeight * 2); }

    bool onAnimate(double nanos) override {
        fStartX = kTileWidth * (1.0f + sinf(nanos * 1e-9)) * 0.5f;
        return true;
    }

    DrawResult onDraw(SkCanvas* canvas, SkString* errorMsg) override {
#if defined(SK_GRAPHITE)
        skgpu::graphite::Recorder* recorder = canvas->recorder();
        if (recorder) {
            this->drawGraphite(canvas, recorder);
            return DrawResult::kOk;
        }
#endif
        return this->drawNonGraphite(canvas, errorMsg);
    }

private:
    static constexpr int kImageSize = 128;
    static constexpr int kPadding = 2;
    static constexpr int kPaddedImageSize = kImageSize + kPadding * 2;
    static constexpr int kTileWidth = kPaddedImageSize * 2;
    static constexpr int kTileHeight = kPaddedImageSize * 2;

    float fStartX = 0.0f;

    sk_sp<SkImage> fImage;

    void drawContent(SkCanvas* canvas, int y) {
        SkPaint gradientPaint;
        constexpr SkPoint points[2] = {{0.0f, 0.0f}, {kImageSize, kImageSize}};
        constexpr SkColor4f colors[4] = {
                SkColors::kRed, SkColors::kGreen, SkColors::kBlue, SkColors::kRed};
        gradientPaint.setShader(SkShaders::LinearGradient(
                points, {{colors, {}, SkTileMode::kClamp}, {}}));

        // Draw image.
        canvas->drawImage(fImage, kPadding, kPadding + y);

        // Draw gradient.
        canvas->save();
        canvas->translate(kPaddedImageSize + kPadding, kPadding + y);
        canvas->drawRect(SkRect::MakeXYWH(0, 0, kImageSize, kImageSize), gradientPaint);
        canvas->restore();
    }

    void drawTile(SkCanvas* canvas) {
        // Clip off the right 1/4 of the tile, after clearing.
        canvas->clear(SkColors::kRed);
        canvas->clipIRect(SkIRect::MakeWH(3 * kTileWidth / 4, kTileHeight));

        // Draw content directly.
        drawContent(canvas, 0);

        // Draw content to a saved layer.
        SkPaint pAlpha;
        pAlpha.setAlphaf(0.5f);
        canvas->saveLayer(nullptr, &pAlpha);
        drawContent(canvas, kPaddedImageSize);
        canvas->restore();
    }

#if defined(SK_GRAPHITE)
    void drawGraphite(SkCanvas* canvas, skgpu::graphite::Recorder* canvasRecorder) {
        SkImageInfo tileImageInfo =
                canvas->imageInfo().makeDimensions(SkISize::Make(kTileWidth, kTileHeight));
        skgpu::graphite::TextureInfo textureInfo =
                static_cast<skgpu::graphite::Surface*>(canvas->getSurface())
                        ->target().proxy()
                        ->textureInfo();

        skgpu::graphite::Context* context = canvasRecorder->priv().context();
        std::unique_ptr<skgpu::graphite::Recorder> recorder =
                context->makeRecorder(ToolUtils::CreateTestingRecorderOptions());
        SkCanvas* recordingCanvas = recorder->makeDeferredCanvas(tileImageInfo, textureInfo);
        this->drawTile(recordingCanvas);
        std::unique_ptr<skgpu::graphite::Recording> recording = recorder->snap();

        // Flush the initial clear added by MakeGraphite.
        std::unique_ptr<skgpu::graphite::Recording> canvasRecording = canvasRecorder->snap();
        context->insertRecording({canvasRecording.get()});

        for (int y = 0; y < 2; ++y) {
            for (int x = 0; x < 2; ++x) {
                context->insertRecording(
                        {recording.get(),
                         canvas->getSurface(),
                         {x * kTileWidth + SkScalarRoundToInt(fStartX), y * kTileHeight}});
            }
        }
    }
#endif

    DrawResult drawNonGraphite(SkCanvas* canvas, SkString* errorMsg) {
        SkImageInfo tileImageInfo =
                canvas->imageInfo().makeDimensions(SkISize::Make(kTileWidth, kTileHeight));

        sk_sp<SkSurface> imageSurface = canvas->makeSurface(tileImageInfo);
        if (!imageSurface) {
            *errorMsg = "Cannot create new SkSurface.";
            return DrawResult::kSkip;
        }

        SkCanvas* imageCanvas = imageSurface->getCanvas();
        this->drawTile(imageCanvas);
        sk_sp<SkImage> image = imageSurface->makeImageSnapshot();

        for (int y = 0; y < 2; ++y) {
            for (int x = 0; x < 2; ++x) {
                canvas->drawImage(image, x * kTileWidth + fStartX, y * kTileHeight);
            }
        }
        return DrawResult::kOk;
    }
};

DEF_GM(return new GraphiteReplayGM;)

}  // namespace skiagm
