/*
* 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 "modules/particles/include/SkParticleBinding.h"

#include "include/core/SkBitmap.h"
#include "include/core/SkContourMeasure.h"
#include "include/core/SkImage.h"
#include "include/core/SkPath.h"
#include "include/utils/SkParsePath.h"
#include "include/utils/SkRandom.h"
#include "include/utils/SkTextUtils.h"
#include "modules/particles/include/SkParticleEffect.h"
#include "modules/particles/include/SkReflected.h"
#include "modules/skresources/include/SkResources.h"
#include "src/sksl/SkSLCompiler.h"

void SkParticleBinding::visitFields(SkFieldVisitor* v) {
    v->visit("Name", fName);
}

class SkEffectExternalValue : public SkParticleExternalValue {
public:
    SkEffectExternalValue(const char* name, SkSL::Compiler& compiler,
                          sk_sp<SkParticleEffectParams> params)
        : SkParticleExternalValue(name, compiler, *compiler.context().fVoid_Type)
        , fParams(std::move(params)) {}

    bool canCall() const override { return true; }
    int callParameterCount() const override { return 1; }
    void getCallParameterTypes(const SkSL::Type** outTypes) const override {
        outTypes[0] = fCompiler.context().fBool_Type.get();
    }

    void call(int index, float* arguments, float* outReturn) override {
        bool loop = ((int*)arguments)[0] != 0;
        fEffect->addSpawnRequest(index, loop, fParams);
    }

private:
    sk_sp<SkParticleEffectParams> fParams;
};

class SkEffectBinding : public SkParticleBinding {
public:
    SkEffectBinding(const char* name = "", sk_sp<SkParticleEffectParams> params = nullptr)
            : SkParticleBinding(name)
            , fParams(std::move(params)) {
        if (!fParams) {
            fParams.reset(new SkParticleEffectParams());
        }
    }

    REFLECTED(SkEffectBinding, SkParticleBinding)

    void visitFields(SkFieldVisitor* v) override {
        SkParticleBinding::visitFields(v);
        fParams->visitFields(v);
    }

    std::unique_ptr<SkParticleExternalValue> toValue(SkSL::Compiler& compiler) override {
        return std::unique_ptr<SkParticleExternalValue>(
            new SkEffectExternalValue(fName.c_str(), compiler, fParams));
    }

    void prepare(const skresources::ResourceProvider* resourceProvider) override {
        fParams->prepare(resourceProvider);
    }

private:
    sk_sp<SkParticleEffectParams> fParams;
};

struct SkPathContours {
    SkScalar fTotalLength;
    SkTArray<sk_sp<SkContourMeasure>> fContours;

    void rebuild(const SkPath& path) {
        fTotalLength = 0;
        fContours.reset();

        SkContourMeasureIter iter(path, false);
        while (auto contour = iter.next()) {
            fContours.push_back(contour);
            fTotalLength += contour->length();
        }
    }
};

// Exposes an SkPath as an external, callable value. p(x) returns a float4 { pos.xy, normal.xy }
class SkPathExternalValue : public SkParticleExternalValue {
public:
    SkPathExternalValue(const char* name, SkSL::Compiler& compiler, const SkPathContours* path)
        : SkParticleExternalValue(name, compiler, *compiler.context().fFloat4_Type)
        , fPath(path) { }

    bool canCall() const override { return true; }
    int callParameterCount() const override { return 1; }
    void getCallParameterTypes(const SkSL::Type** outTypes) const override {
        outTypes[0] = fCompiler.context().fFloat_Type.get();
    }

    void call(int index, float* arguments, float* outReturn) override {
        SkScalar len = fPath->fTotalLength * arguments[0];
        int idx = 0;
        while (idx < fPath->fContours.count() - 1 && len > fPath->fContours[idx]->length()) {
            len -= fPath->fContours[idx++]->length();
        }
        SkVector localXAxis;
        if (idx >= fPath->fContours.count() ||
            !fPath->fContours[idx]->getPosTan(len, (SkPoint*)outReturn, &localXAxis)) {
            outReturn[0] = outReturn[1] = 0.0f;
            localXAxis = { 1, 0 };
        }
        outReturn[2] = localXAxis.fY;
        outReturn[3] = -localXAxis.fX;
    }

private:
    const SkPathContours* fPath;
};

class SkPathBinding : public SkParticleBinding {
public:
    SkPathBinding(const char* name = "", const char* path = "")
            : SkParticleBinding(name)
            , fPath(path) {}

    REFLECTED(SkPathBinding, SkParticleBinding)

    void visitFields(SkFieldVisitor* v) override {
        SkParticleBinding::visitFields(v);
        v->visit("Path", fPath);
    }

    std::unique_ptr<SkParticleExternalValue> toValue(SkSL::Compiler& compiler) override {
        return std::unique_ptr<SkParticleExternalValue>(
            new SkPathExternalValue(fName.c_str(), compiler, &fContours));
    }

    void prepare(const skresources::ResourceProvider*) override {
        SkPath path;
        if (SkParsePath::FromSVGString(fPath.c_str(), &path)) {
            fContours.rebuild(path);
        }
    }

private:
    SkString fPath;

    // Cached
    SkPathContours fContours;
};

class SkTextBinding : public SkParticleBinding {
public:
    SkTextBinding(const char* name = "", const char* text = "", SkScalar fontSize = 96)
            : SkParticleBinding(name)
            , fText(text)
            , fFontSize(fontSize) {}

    REFLECTED(SkTextBinding, SkParticleBinding)

    void visitFields(SkFieldVisitor* v) override {
        SkParticleBinding::visitFields(v);
        v->visit("Text", fText);
        v->visit("FontSize", fFontSize);
    }

    std::unique_ptr<SkParticleExternalValue> toValue(SkSL::Compiler& compiler) override {
        return std::unique_ptr<SkParticleExternalValue>(
            new SkPathExternalValue(fName.c_str(), compiler, &fContours));
    }

    void prepare(const skresources::ResourceProvider*) override {
        if (fText.isEmpty()) {
            return;
        }

        SkFont font(nullptr, fFontSize);
        SkPath path;
        SkTextUtils::GetPath(fText.c_str(), fText.size(), SkTextEncoding::kUTF8, 0, 0, font, &path);
        fContours.rebuild(path);
    }

private:
    SkString fText;
    SkScalar fFontSize;

    // Cached
    SkPathContours fContours;
};

// Exposes an SkBitmap as an external, callable value. p(xy) returns a float4
class SkBitmapExternalValue : public SkParticleExternalValue {
public:
    SkBitmapExternalValue(const char* name, SkSL::Compiler& compiler, const SkBitmap& bitmap)
            : SkParticleExternalValue(name, compiler, *compiler.context().fFloat4_Type)
            , fBitmap(bitmap) {
        SkASSERT(bitmap.colorType() == kRGBA_F32_SkColorType);
    }

    bool canCall() const override { return true; }
    int callParameterCount() const override { return 1; }
    void getCallParameterTypes(const SkSL::Type** outTypes) const override {
        outTypes[0] = fCompiler.context().fFloat2_Type.get();
    }

    void call(int index, float* arguments, float* outReturn) override {
        int x = SkTPin(static_cast<int>(arguments[0] * fBitmap.width()), 0, fBitmap.width() - 1);
        int y = SkTPin(static_cast<int>(arguments[1] * fBitmap.height()), 0, fBitmap.height() - 1);
        float* p = static_cast<float*>(fBitmap.getAddr(x, y));
        memcpy(outReturn, p, 4 * sizeof(float));
    }

private:
    SkBitmap fBitmap;
};

class SkImageBinding : public SkParticleBinding {
public:
    SkImageBinding(const char* name = "", const char* imagePath = "", const char* imageName = "")
            : SkParticleBinding(name)
            , fImagePath(imagePath)
            , fImageName(imageName) {}

    REFLECTED(SkImageBinding, SkParticleBinding)

    void visitFields(SkFieldVisitor* v) override {
        SkParticleBinding::visitFields(v);
        v->visit("ImagePath", fImagePath);
        v->visit("ImageName", fImageName);
    }

    std::unique_ptr<SkParticleExternalValue> toValue(SkSL::Compiler& compiler) override {
        return std::unique_ptr<SkParticleExternalValue>(
            new SkBitmapExternalValue(fName.c_str(), compiler, fBitmap));
    }

    void prepare(const skresources::ResourceProvider* resourceProvider) override {
        if (auto asset = resourceProvider->loadImageAsset(fImagePath.c_str(), fImageName.c_str(),
                                                          nullptr)) {
            if (auto image = asset->getFrame(0)) {
                fBitmap.allocPixels(image->imageInfo().makeColorType(kRGBA_F32_SkColorType));
                image->readPixels(fBitmap.pixmap(), 0, 0);
                return;
            }
        }

        fBitmap.allocPixels(SkImageInfo::Make(1, 1, kRGBA_F32_SkColorType, kPremul_SkAlphaType));
        fBitmap.eraseColor(SK_ColorWHITE);
    }

private:
    SkString fImagePath;
    SkString fImageName;

    // Cached
    SkBitmap fBitmap;
};

sk_sp<SkParticleBinding> SkParticleBinding::MakeEffectBinding(
    const char* name, sk_sp<SkParticleEffectParams> params) {
    return sk_sp<SkParticleBinding>(new SkEffectBinding(name, params));
}

sk_sp<SkParticleBinding> SkParticleBinding::MakePathBinding(const char* name, const char* path) {
    return sk_sp<SkParticleBinding>(new SkPathBinding(name, path));
}

void SkParticleBinding::RegisterBindingTypes() {
    REGISTER_REFLECTED(SkParticleBinding);
    REGISTER_REFLECTED(SkEffectBinding);
    REGISTER_REFLECTED(SkImageBinding);
    REGISTER_REFLECTED(SkPathBinding);
    REGISTER_REFLECTED(SkTextBinding);
}
