/*
 * Copyright 2021 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"

#if !defined(SK_BUILD_FOR_GOOGLE3)  // Google3 doesn't build particles module
#if !defined(SK_BUILD_FOR_SKQP)  // SkQP doesn't need to test particles

#include "include/core/SkCanvas.h"
#include "include/core/SkColor.h"
#include "modules/particles/include/SkParticleEffect.h"
#include "modules/particles/include/SkParticleSerialization.h"
#include "modules/skresources/include/SkResources.h"
#include "src/sksl/codegen/SkSLVMCodeGenerator.h"
#include "tools/Resources.h"

struct UniformValue {
    const char*        fName;
    std::vector<float> fData;
};

class ParticlesGM : public skiagm::GM {
public:
    ParticlesGM(const char* name,
                double startTime,
                SkISize size,
                SkPoint origin,
                std::vector<UniformValue> uniforms = {})
            : GM(SK_ColorBLACK)
            , fName(name)
            , fStartTime(startTime)
            , fSize(size)
            , fOrigin(origin)
            , fUniforms(std::move(uniforms)) {}

    SkString onShortName() override { return SkStringPrintf("particles_%s", fName); }
    SkISize onISize() override { return fSize; }

    void onOnceBeforeDraw() override {
        SkParticleEffect::RegisterParticleTypes();

        auto jsonData = GetResourceAsData(SkStringPrintf("particles/%s.json", fName).c_str());
        skjson::DOM dom(static_cast<const char*>(jsonData->data()), jsonData->size());
        SkFromJsonVisitor fromJson(dom.root());

        auto resourceProvider = skresources::FileResourceProvider::Make(GetResourcePath());
        auto effectParams = sk_make_sp<SkParticleEffectParams>();
        effectParams->visitFields(&fromJson);
        effectParams->prepare(resourceProvider.get());

        fEffect = sk_make_sp<SkParticleEffect>(effectParams);
        for (const auto& val : fUniforms) {
            SkAssertResult(fEffect->setUniform(val.fName, val.fData.data(), val.fData.size()));
        }

        fEffect->start(/*now=*/0.0, /*looping=*/true);

        // Fast-forward (in 30 fps time-slices) to the requested time
        for (double time = 0; time < fStartTime; time += 1.0 / 30) {
            fEffect->update(/*now=*/std::min(time, fStartTime));
        }
    }

    bool onAnimate(double nanos) override {
        if (fEffect) {
            fEffect->update(fStartTime + (nanos * 1E-9));
        }
        return true;
    }

    void onDraw(SkCanvas* canvas) override {
        canvas->save();
        canvas->translate(fOrigin.fX, fOrigin.fY);
        fEffect->draw(canvas);
        canvas->restore();
    }

protected:
    const char*               fName;
    const double              fStartTime;
    const SkISize             fSize;
    const SkPoint             fOrigin;
    sk_sp<SkParticleEffect>   fEffect;
    std::vector<UniformValue> fUniforms;
};

DEF_GM(return new ParticlesGM("confetti",     1.0, {400, 400}, {200, 200});)
DEF_GM(return new ParticlesGM("cube",         1.0, {400, 400}, {200, 200});)
DEF_GM(return new ParticlesGM("curves",       4.0, {100, 200}, { 50, 190});)
DEF_GM(return new ParticlesGM("mandrill",     1.0, {250, 250}, { 25,  25});)
DEF_GM(return new ParticlesGM("spiral",       2.0, {250, 250}, {125, 125});)
DEF_GM(return new ParticlesGM("sprite_frame", 1.0, {200, 200}, {100, 100});)
DEF_GM(return new ParticlesGM("text",         1.0, {250, 110}, { 10, 100});)
DEF_GM(return new ParticlesGM("uniforms",     2.0, {250, 250}, {125, 125},
                                              {{"rate",  {2.0f}},
                                               {"spin",  {4.0f}},
                                               {"color", {0.25f, 0.75f, 0.75f}}});)

#endif  // SK_BUILD_FOR_SKQP
#endif  // SK_BUILD_FOR_GOOGLE3
