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

#ifndef skiagm_DEFINED
#define skiagm_DEFINED

#include "gm/verifiers/gmverifier.h"
#include "include/core/SkColor.h"
#include "include/core/SkScalar.h"
#include "include/core/SkSize.h"
#include "include/core/SkString.h"
#include "include/core/SkTypes.h"
#include "include/private/base/SkMacros.h"
#include "tools/Registry.h"

#include <memory>

class GrDirectContext;
class GrRecordingContext;
class SkCanvas;
class SkMetaData;
struct GrContextOptions;

namespace skgpu::graphite {
class Context;
}

#define DEF_GM(CODE)                                         \
    static skiagm::GMRegistry SK_MACRO_APPEND_COUNTER(REG_)( \
            []() { return std::unique_ptr<skiagm::GM>([]() { CODE; }()); });

// A Simple GM is a rendering test that does not store state between rendering calls or make use of
// the onOnceBeforeDraw() virtual; it consists of:
//   *   A name.
//   *   Prefered width and height.
//   *   Optionally, a background color (default is white).
//   *   A standalone function pointer that implements its onDraw method.
#define DEF_SIMPLE_GM(NAME, CANVAS, W, H) \
    DEF_SIMPLE_GM_BG_NAME(NAME, CANVAS, W, H, SK_ColorWHITE, SkString(#NAME))
#define DEF_SIMPLE_GM_BG(NAME, CANVAS, W, H, BGCOLOR) \
    DEF_SIMPLE_GM_BG_NAME(NAME, CANVAS, W, H, BGCOLOR, SkString(#NAME))
#define DEF_SIMPLE_GM_BG_NAME(NAME, CANVAS, W, H, BGCOLOR, NAME_STR) \
    static void SK_MACRO_CONCAT(NAME,_GM_inner)(SkCanvas*); \
    DEF_SIMPLE_GM_BG_NAME_CAN_FAIL(NAME, CANVAS,, W, H, BGCOLOR, NAME_STR) { \
        SK_MACRO_CONCAT(NAME,_GM_inner)(CANVAS); \
        return skiagm::DrawResult::kOk; \
    } \
    void SK_MACRO_CONCAT(NAME,_GM_inner)(SkCanvas* CANVAS)

#define DEF_SIMPLE_GM_CAN_FAIL(NAME, CANVAS, ERR_MSG, W, H) \
    DEF_SIMPLE_GM_BG_NAME_CAN_FAIL(NAME, CANVAS, ERR_MSG, W, H, SK_ColorWHITE, SkString(#NAME))
#define DEF_SIMPLE_GM_BG_CAN_FAIL(NAME, CANVAS, ERR_MSG, W, H, BGCOLOR) \
    DEF_SIMPLE_GM_BG_NAME_CAN_FAIL(NAME, CANVAS, ERR_MSG, W, H, BGCOLOR, SkString(#NAME))
#define DEF_SIMPLE_GM_BG_NAME_CAN_FAIL(NAME, CANVAS, ERR_MSG, W, H, BGCOLOR, NAME_STR) \
    static skiagm::DrawResult SK_MACRO_CONCAT(NAME,_GM)(SkCanvas*, SkString*); \
    DEF_GM(return new skiagm::SimpleGM(BGCOLOR, NAME_STR, {W,H}, SK_MACRO_CONCAT(NAME,_GM));) \
    skiagm::DrawResult SK_MACRO_CONCAT(NAME,_GM)(SkCanvas* CANVAS, SkString* ERR_MSG)


// A Simple GpuGM makes direct GPU calls. Its onDraw hook that includes GPU objects as params, and
// is only invoked on GPU configs. Non-GPU configs automatically draw a GPU-only message and abort.
#define DEF_SIMPLE_GPU_GM(NAME, GR_CONTEXT, CANVAS, W, H)                                         \
    DEF_SIMPLE_GPU_GM_BG(NAME, GR_CONTEXT, CANVAS, W, H, SK_ColorWHITE)

#define DEF_SIMPLE_GPU_GM_BG(NAME, GR_CONTEXT, CANVAS, W, H, BGCOLOR)                             \
    static void SK_MACRO_CONCAT(NAME,_GM_inner)(GrRecordingContext*, SkCanvas*);                  \
    DEF_SIMPLE_GPU_GM_BG_CAN_FAIL(NAME, GR_CONTEXT, CANVAS, /* ERR_MSG */, W, H, BGCOLOR) {       \
        SK_MACRO_CONCAT(NAME,_GM_inner)(GR_CONTEXT, CANVAS);                                      \
        return skiagm::DrawResult::kOk;                                                           \
    }                                                                                             \
    void SK_MACRO_CONCAT(NAME,_GM_inner)(GrRecordingContext* GR_CONTEXT, SkCanvas* CANVAS)

#define DEF_SIMPLE_GPU_GM_CAN_FAIL(NAME, GR_CONTEXT, CANVAS, ERR_MSG, W, H)                       \
    DEF_SIMPLE_GPU_GM_BG_CAN_FAIL(NAME, GR_CONTEXT, CANVAS, ERR_MSG, W, H, SK_ColorWHITE)

#define DEF_SIMPLE_GPU_GM_BG_CAN_FAIL(NAME, GR_CONTEXT, CANVAS, ERR_MSG, W, H, BGCOLOR)           \
    static skiagm::DrawResult SK_MACRO_CONCAT(NAME,_GM)(                                          \
        GrRecordingContext*, SkCanvas*, SkString*);                                               \
    DEF_GM(return new skiagm::SimpleGpuGM(BGCOLOR, SkString(#NAME), {W,H},                        \
                                          SK_MACRO_CONCAT(NAME,_GM));)                            \
    skiagm::DrawResult SK_MACRO_CONCAT(NAME,_GM)(                                                 \
            GrRecordingContext* GR_CONTEXT, SkCanvas* CANVAS, SkString* ERR_MSG)

namespace skiagm {

    enum class DrawResult {
        kOk,   // Test drew successfully.
        kFail, // Test failed to draw.
        kSkip  // Test is not applicable in this context and should be skipped.
    };

    class GM {
    public:
        using DrawResult = skiagm::DrawResult;

        GM(SkColor backgroundColor = SK_ColorWHITE);
        virtual ~GM();

        enum Mode {
            kGM_Mode,
            kSample_Mode,
            kBench_Mode,
        };

        void setMode(Mode mode) { fMode = mode; }
        Mode getMode() const { return fMode; }

        inline static constexpr char kErrorMsg_DrawSkippedGpuOnly[] =
                "This test is for GPU configs only.";

        inline static constexpr char kErrorMsg_DrawSkippedGraphiteOnly[] =
                "This test is for Graphite only.";

        DrawResult gpuSetup(GrDirectContext* context, SkCanvas* canvas) {
            SkString errorMsg;
            return this->gpuSetup(context, canvas, &errorMsg);
        }
        DrawResult gpuSetup(GrDirectContext*, SkCanvas*, SkString* errorMsg);
        void gpuTeardown();

        void onceBeforeDraw() {
            if (!fHaveCalledOnceBeforeDraw) {
                fHaveCalledOnceBeforeDraw = true;
                this->onOnceBeforeDraw();
            }
        }

        DrawResult draw(SkCanvas* canvas) {
            SkString errorMsg;
            return this->draw(canvas, &errorMsg);
        }
        DrawResult draw(SkCanvas*, SkString* errorMsg);
        DrawResult draw(skgpu::graphite::Context*, SkCanvas*, SkString* errorMsg);

        void drawBackground(SkCanvas*);
        DrawResult drawContent(SkCanvas* canvas) {
            SkString errorMsg;
            return this->drawContent(canvas, &errorMsg);
        }
        DrawResult drawContent(SkCanvas*, SkString* errorMsg);
        DrawResult drawContent(skgpu::graphite::Context*, SkCanvas*, SkString* errorMsg);

        SkISize getISize() { return this->onISize(); }
        const char* getName();

        virtual bool runAsBench() const;

        SkScalar width() {
            return SkIntToScalar(this->getISize().width());
        }
        SkScalar height() {
            return SkIntToScalar(this->getISize().height());
        }

        SkColor getBGColor() const { return fBGColor; }
        void setBGColor(SkColor);

        // helper: fill a rect in the specified color based on the GM's getISize bounds.
        void drawSizeBounds(SkCanvas*, SkColor);

        bool animate(double /*nanos*/);
        virtual bool onChar(SkUnichar);

        bool getControls(SkMetaData* controls) { return this->onGetControls(controls); }
        void setControls(const SkMetaData& controls) { this->onSetControls(controls); }

        virtual void modifyGrContextOptions(GrContextOptions*);

        virtual std::unique_ptr<verifiers::VerifierList> getVerifiers() const;

    protected:
        // onGpuSetup is called once before any other processing with a direct context.
        virtual DrawResult onGpuSetup(GrDirectContext*, SkString*) { return DrawResult::kOk; }
        virtual void onGpuTeardown() {}
        virtual void onOnceBeforeDraw();
        virtual DrawResult onDraw(skgpu::graphite::Context*, SkCanvas*, SkString* errorMsg);
        virtual DrawResult onDraw(SkCanvas*, SkString* errorMsg);
        virtual void onDraw(SkCanvas*);

        virtual SkISize onISize() = 0;
        virtual SkString onShortName() = 0;

        virtual bool onAnimate(double /*nanos*/);
        virtual bool onGetControls(SkMetaData*);
        virtual void onSetControls(const SkMetaData&);

    private:
        Mode       fMode;
        SkString   fShortName;
        SkColor    fBGColor;
        bool       fHaveCalledOnceBeforeDraw = false;
        bool       fGpuSetup = false;
        DrawResult fGpuSetupResult = DrawResult::kOk;
    };

    using GMFactory = std::unique_ptr<skiagm::GM> (*)();
    using GMRegistry = sk_tools::Registry<GMFactory>;

    // A GpuGM replaces the onDraw method with one that also accepts GPU objects alongside the
    // SkCanvas. Its onDraw is only invoked on GPU configs; on non-GPU configs it will automatically
    // draw a GPU-only message and abort.
    class GpuGM : public GM {
    public:
        GpuGM(SkColor backgroundColor = SK_ColorWHITE) : GM(backgroundColor) {}

        // TODO(tdenniston): Currently GpuGMs don't have verifiers (because they do not render on
        //   CPU), but we may want to be able to verify the output images standalone, without
        //   requiring a gold image for comparison.
        std::unique_ptr<verifiers::VerifierList> getVerifiers() const override { return nullptr; }

    private:
        using GM::onDraw;
        DrawResult onDraw(SkCanvas*, SkString* errorMsg) final;

        virtual DrawResult onDraw(GrRecordingContext*, SkCanvas*, SkString* errorMsg);
        virtual void onDraw(GrRecordingContext*, SkCanvas*);
    };

    // A GraphiteGM replaces the onDraw method with one that also accepts Graphite Context objects
    // alongside the SkCanvas. Its onDraw is only invoked on Graphite configs; on non-Graphite
    // configs it will automatically draw a "Graphite-only" message and abort.
    class GraphiteGM : public GM {
    public:
        GraphiteGM(SkColor backgroundColor = SK_ColorWHITE) : GM(backgroundColor) {}

    private:
        using GM::onDraw;
        DrawResult onDraw(SkCanvas*, SkString* errorMsg) final;

        DrawResult onDraw(skgpu::graphite::Context*, SkCanvas*, SkString* errorMsg) override;
        virtual void onDraw(skgpu::graphite::Context*, SkCanvas*);
    };

    // SimpleGM is intended for basic GMs that can define their entire implementation inside a
    // single "draw" function pointer.
    class SimpleGM : public GM {
    public:
        using DrawProc = DrawResult(*)(SkCanvas*, SkString*);

        SimpleGM(SkColor bgColor, const SkString& name, const SkISize& size, DrawProc drawProc)
                : GM(bgColor), fName(name), fSize(size), fDrawProc(drawProc) {}

    private:
        SkISize onISize() override;
        SkString onShortName() override;
        DrawResult onDraw(SkCanvas* canvas, SkString* errorMsg) override;

        const SkString fName;
        const SkISize fSize;
        const DrawProc fDrawProc;
    };

    class SimpleGpuGM : public GpuGM {
    public:
        using DrawProc = DrawResult (*)(GrRecordingContext*, SkCanvas*, SkString* errorMsg);

        SimpleGpuGM(SkColor bgColor, const SkString& name, const SkISize& size, DrawProc drawProc)
                : GpuGM(bgColor), fName(name), fSize(size), fDrawProc(drawProc) {}

    private:
        SkISize onISize() override;
        SkString onShortName() override;
        DrawResult onDraw(GrRecordingContext*, SkCanvas*, SkString* errorMsg) override;

        const SkString fName;
        const SkISize fSize;
        const DrawProc fDrawProc;
    };
}  // namespace skiagm

void MarkGMGood(SkCanvas*, SkScalar x, SkScalar y);
void MarkGMBad (SkCanvas*, SkScalar x, SkScalar y);

#endif
