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

#include "include/core/SkCanvas.h"
#include "src/core/SkPathPriv.h"
#include "tools/viewer/ClickHandlerSlide.h"

#if defined(SK_GANESH)

#include "include/core/SkFont.h"
#include "src/core/SkCanvasPriv.h"
#include "src/gpu/ganesh/GrCanvas.h"
#include "src/gpu/ganesh/GrCaps.h"
#include "src/gpu/ganesh/GrOpFlushState.h"
#include "src/gpu/ganesh/GrRecordingContextPriv.h"
#include "src/gpu/ganesh/SurfaceDrawContext.h"
#include "src/gpu/ganesh/ops/GrDrawOp.h"
#include "src/gpu/ganesh/ops/GrSimpleMeshDrawOpHelper.h"
#include "src/gpu/ganesh/ops/TessellationPathRenderer.h"
#include "src/gpu/ganesh/tessellate/GrPathTessellationShader.h"
#include "src/gpu/ganesh/tessellate/PathTessellator.h"
#include "src/gpu/tessellate/AffineMatrix.h"
#include "src/gpu/tessellate/MiddleOutPolygonTriangulator.h"
#include "tools/fonts/FontToolUtils.h"

namespace skgpu::ganesh {

namespace {

enum class Mode {
    kWedgeMiddleOut,
    kCurveMiddleOut
};

static const char* ModeName(Mode mode) {
    switch (mode) {
        case Mode::kWedgeMiddleOut:
            return "MiddleOutShader (kWedges)";
        case Mode::kCurveMiddleOut:
            return "MiddleOutShader (kCurves)";
    }
    SkUNREACHABLE;
}

// Draws a path directly to the screen using a specific tessellator.
class SamplePathTessellatorOp : public GrDrawOp {
private:
    DEFINE_OP_CLASS_ID

    SamplePathTessellatorOp(const SkRect& drawBounds, const SkPath& path, const SkMatrix& m,
                            GrPipeline::InputFlags pipelineFlags, Mode mode)
            : GrDrawOp(ClassID())
            , fPath(path)
            , fMatrix(m)
            , fPipelineFlags(pipelineFlags)
            , fMode(mode) {
        this->setBounds(drawBounds, HasAABloat::kNo, IsHairline::kNo);
    }
    const char* name() const override { return "SamplePathTessellatorOp"; }
    void visitProxies(const GrVisitProxyFunc&) const override {}
    FixedFunctionFlags fixedFunctionFlags() const override {
        return FixedFunctionFlags::kUsesHWAA;
    }
    GrProcessorSet::Analysis finalize(const GrCaps& caps, const GrAppliedClip* clip,
                                      GrClampType clampType) override {
        SkPMColor4f color;
        return fProcessors.finalize(SK_PMColor4fWHITE, GrProcessorAnalysisCoverage::kNone, clip,
                                    nullptr, caps, clampType, &color);
    }
    void onPrePrepare(GrRecordingContext*, const GrSurfaceProxyView&, GrAppliedClip*,
                      const GrDstProxyView&, GrXferBarrierFlags, GrLoadOp colorLoadOp) override {}
    void onPrepare(GrOpFlushState* flushState) override {
        constexpr static SkPMColor4f kCyan = {0,1,1,1};
        auto alloc = flushState->allocator();
        const SkMatrix& shaderMatrix = SkMatrix::I();
        const SkMatrix& pathMatrix = fMatrix;
        const GrCaps& caps = flushState->caps();
        const GrShaderCaps& shaderCaps = *caps.shaderCaps();

        PathTessellator::PathDrawList pathList{pathMatrix, fPath, kCyan};
        if (fMode == Mode::kCurveMiddleOut) {
#if !defined(SK_ENABLE_OPTIMIZE_SIZE)
            // This emulates what PathStencilCoverOp does when using curves, except we include the
            // middle-out triangles directly in the written patches for convenience (normally they
            // use a simple triangle pipeline). But PathCurveTessellator only knows how to read
            // extra triangles from BreadcrumbTriangleList, so build on from the middle-out stack.
            SkArenaAlloc storage{256};
            GrInnerFanTriangulator::BreadcrumbTriangleList triangles;
            for (tess::PathMiddleOutFanIter it(fPath); !it.done();) {
                for (auto [p0, p1, p2] : it.nextStack()) {
                    triangles.append(&storage,
                                     pathMatrix.mapPoint(p0),
                                     pathMatrix.mapPoint(p1),
                                     pathMatrix.mapPoint(p2),
                                     /*winding=*/1);
                }
            }

            auto* tess = PathCurveTessellator::Make(alloc, shaderCaps.fInfinitySupport);
            tess->prepareWithTriangles(flushState, shaderMatrix, &triangles, pathList,
                                       fPath.countVerbs());
            fTessellator = tess;
#else
            auto* tess = PathCurveTessellator::Make(alloc, shaderCaps.fInfinitySupport);
            tess->prepareWithTriangles(flushState, shaderMatrix, nullptr, pathList,
                                       fPath.countVerbs());
            fTessellator = tess;
#endif
        } else {
            // This emulates what PathStencilCoverOp does when using wedges.
            fTessellator = PathWedgeTessellator::Make(alloc, shaderCaps.fInfinitySupport);
            fTessellator->prepare(flushState, shaderMatrix, pathList, fPath.countVerbs());
        }

        auto pipeline = GrSimpleMeshDrawOpHelper::CreatePipeline(flushState, std::move(fProcessors),
                                                                 fPipelineFlags);
        auto* tessShader = GrPathTessellationShader::Make(*caps.shaderCaps(),
                                                          alloc,
                                                          shaderMatrix,
                                                          kCyan,
                                                          fTessellator->patchAttribs());
        fProgram = GrTessellationShader::MakeProgram({alloc, flushState->writeView(),
                                                     flushState->usesMSAASurface(),
                                                     &flushState->dstProxyView(),
                                                     flushState->renderPassBarriers(),
                                                     GrLoadOp::kClear, &flushState->caps()},
                                                     tessShader,
                                                     pipeline,
                                                     &GrUserStencilSettings::kUnused);
    }

    void onExecute(GrOpFlushState* flushState, const SkRect& chainBounds) override {
        flushState->bindPipeline(*fProgram, chainBounds);
        fTessellator->draw(flushState);
    }

    const SkPath fPath;
    const SkMatrix fMatrix;
    const GrPipeline::InputFlags fPipelineFlags;
    const Mode fMode;
    PathTessellator* fTessellator = nullptr;
    GrProgramInfo* fProgram;
    GrProcessorSet fProcessors{SkBlendMode::kSrcOver};

    friend class GrOp;  // For ctor.
};

}  // namespace

// This slide enables wireframe and visualizes the triangles generated by path tessellators.
class PathTessellatorsSlide : public ClickHandlerSlide {
public:
    PathTessellatorsSlide() {
#if 0
        // For viewing middle-out triangulations of the inner fan.
        fPath.moveTo(1, 0);
        int numSides = 32 * 3;
        for (int i = 1; i < numSides; ++i) {
            float theta = 2*3.1415926535897932384626433832785 * i / numSides;
            fPath.lineTo(std::cos(theta), std::sin(theta));
        }
        fPath.transform(SkMatrix::Scale(200, 200));
        fPath.transform(SkMatrix::Translate(300, 300));
#else
        fPath = SkPathBuilder()
                .moveTo(100, 500)
                .cubicTo(300, 400, -100, 300, 100, 200)
                .quadTo(250, 0, 400, 200)
                .conicTo(600, 350, 400, 500, fConicWeight)
                .close()
                .detach();
#endif
        fName = "PathTessellators";
    }

    bool onChar(SkUnichar) override;

    void draw(SkCanvas*) override;

protected:
    Click* onFindClickHandler(SkScalar x, SkScalar y, skui::ModifierKey) override;
    bool onClick(Click*) override;

    SkPath fPath;
    GrPipeline::InputFlags fPipelineFlags = GrPipeline::InputFlags::kWireframe;
    Mode fMode = Mode::kWedgeMiddleOut;

    float fConicWeight = .5;

    class Click;
};

void PathTessellatorsSlide::draw(SkCanvas* canvas) {
    canvas->clear(SK_ColorBLACK);

    auto ctx = canvas->recordingContext();
    auto sdc = skgpu::ganesh::TopDeviceSurfaceDrawContext(canvas);

    SkString error;
    if (!sdc || !ctx) {
        error = "GPU Only.";
    } else if (!skgpu::ganesh::TessellationPathRenderer::IsSupported(*ctx->priv().caps())) {
        error = "TessellationPathRenderer not supported.";
    }
    if (!error.isEmpty()) {
        canvas->clear(SK_ColorRED);
        SkFont font(ToolUtils::DefaultTypeface(), 20);
        SkPaint captionPaint;
        captionPaint.setColor(SK_ColorWHITE);
        canvas->drawString(error.c_str(), 10, 30, font, captionPaint);
        return;
    }

    sdc->addDrawOp(GrOp::Make<SamplePathTessellatorOp>(ctx,
                                                       sdc->asRenderTargetProxy()->getBoundsRect(),
                                                       fPath, canvas->getTotalMatrix(),
                                                       fPipelineFlags, fMode));

    // Draw the path points.
    SkPaint pointsPaint;
    pointsPaint.setColor(SK_ColorBLUE);
    pointsPaint.setStrokeWidth(8);
    SkPath devPath = fPath.makeTransform(canvas->getTotalMatrix());
    {
        SkAutoCanvasRestore acr(canvas, true);
        canvas->setMatrix(SkMatrix::I());
        SkString caption(ModeName(fMode));
        caption.appendf(" (w=%g)", fConicWeight);
        SkFont font(ToolUtils::DefaultTypeface(), 20);
        SkPaint captionPaint;
        captionPaint.setColor(SK_ColorWHITE);
        canvas->drawString(caption, 10, 30, font, captionPaint);
        canvas->drawPoints(SkCanvas::kPoints_PointMode, devPath.points(), pointsPaint);
    }
}

class PathTessellatorsSlide::Click : public ClickHandlerSlide::Click {
public:
    Click(int ptIdx) : fPtIdx(ptIdx) {}

    void doClick(SkPath* path) {
        SkPoint pt = path->points()[fPtIdx];
        SkPathBuilder builder(*path);
        builder.setPoint(fPtIdx, pt + fCurr - fPrev);
        *path = builder.detach();
    }

private:
    int fPtIdx;
};

ClickHandlerSlide::Click* PathTessellatorsSlide::onFindClickHandler(SkScalar x, SkScalar y,
                                                                    skui::ModifierKey) {
    SkSpan<const SkPoint> pts = fPath.points();
    float fuzz = 30;
    for (int i = 0; i < fPath.countPoints(); ++i) {
        if (fabs(x - pts[i].x()) < fuzz && fabsf(y - pts[i].y()) < fuzz) {
            return new Click(i);
        }
    }
    return nullptr;
}

bool PathTessellatorsSlide::onClick(ClickHandlerSlide::Click* click) {
    Click* myClick = (Click*)click;
    myClick->doClick(&fPath);
    return true;
}

static SkPath update_weight(const SkPath& path, float w) {
    SkPathBuilder path_;
    for (auto [verb, pts, _] : SkPathPriv::Iterate(path)) {
        switch (verb) {
            case SkPathVerb::kMove:
                path_.moveTo(pts[0]);
                break;
            case SkPathVerb::kLine:
                path_.lineTo(pts[1]);
                break;
            case SkPathVerb::kQuad:
                path_.quadTo(pts[1], pts[2]);
                break;
            case SkPathVerb::kCubic:
                path_.cubicTo(pts[1], pts[2], pts[3]);
                break;
            case SkPathVerb::kConic:
                path_.conicTo(pts[1], pts[2], (w != 1) ? w : .99f);
                break;
            case SkPathVerb::kClose:
                break;
        }
    }
    return path_.detach();
}

bool PathTessellatorsSlide::onChar(SkUnichar unichar) {
    switch (unichar) {
        case 'w':
            fPipelineFlags = (GrPipeline::InputFlags)(
                    (int)fPipelineFlags ^ (int)GrPipeline::InputFlags::kWireframe);
            return true;
        case 'D': {
            fPath.dump();
            return true;
        }
        case '+':
            fConicWeight *= 2;
            fPath = update_weight(fPath, fConicWeight);
            return true;
        case '=':
            fConicWeight *= 5/4.f;
            fPath = update_weight(fPath, fConicWeight);
            return true;
        case '_':
            fConicWeight *= .5f;
            fPath = update_weight(fPath, fConicWeight);
            return true;
        case '-':
            fConicWeight *= 4/5.f;
            fPath = update_weight(fPath, fConicWeight);
            return true;
        case '1':
        case '2':
            fMode = (Mode)(unichar - '1');
            return true;
    }
    return false;
}

DEF_SLIDE( return new PathTessellatorsSlide; )

}  // namespace skgpu::ganesh

#endif  // defined(SK_GANESH)
