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

#include "modules/skottie/src/effects/Effects.h"

#include "modules/skottie/src/SkottieAdapter.h"
#include "modules/skottie/src/SkottieValue.h"
#include "modules/sksg/include/SkSGGradient.h"
#include "modules/sksg/include/SkSGRenderEffect.h"
#include "src/utils/SkJSON.h"

namespace skottie {
namespace internal {

namespace  {

class GradientRampEffectAdapter final : public SkNVRefCnt<GradientRampEffectAdapter> {
public:
    explicit GradientRampEffectAdapter(sk_sp<sksg::RenderNode> child)
        : fRoot(sksg::ShaderEffect::Make(std::move(child))) {}

    ADAPTER_PROPERTY(StartPoint, SkPoint , SkPoint::Make(0, 0))
    ADAPTER_PROPERTY(EndPoint  , SkPoint , SkPoint::Make(0, 0))
    ADAPTER_PROPERTY(StartColor, SkColor ,       SK_ColorBLACK)
    ADAPTER_PROPERTY(EndColor  , SkColor ,       SK_ColorBLACK)
    ADAPTER_PROPERTY(Blend     , SkScalar,                   0)
    ADAPTER_PROPERTY(Scatter   , SkScalar,                   0)

    // Really an enum: 1 -> linear, 7 -> radial (?!)
    ADAPTER_PROPERTY(Shape     , SkScalar,                   0)

    const sk_sp<sksg::ShaderEffect>& root() const { return fRoot; }

private:
    enum class InstanceType {
        kNone,
        kLinear,
        kRadial,
    };

    void apply() {
        // This adapter manages a SG fragment with the following structure:
        //
        // - ShaderEffect [fRoot]
        //     \  GradientShader [fGradient]
        //     \  child/wrapped fragment
        //
        // The gradient shader is updated based on the (animatable) instance type (linear/radial).

        auto update_gradient = [this] (InstanceType new_type) {
            if (new_type != fInstanceType) {
                fGradient = new_type == InstanceType::kLinear
                        ? sk_sp<sksg::Gradient>(sksg::LinearGradient::Make())
                        : sk_sp<sksg::Gradient>(sksg::RadialGradient::Make());

                fRoot->setShader(fGradient);
                fInstanceType = new_type;
            }

            fGradient->setColorStops({ {0, fStartColor}, {1, fEndColor} });
        };

        static constexpr int kLinearShapeValue = 1;
        const auto instance_type = (SkScalarRoundToInt(fShape) == kLinearShapeValue)
                ? InstanceType::kLinear
                : InstanceType::kRadial;

        // Sync the gradient shader instance if needed.
        update_gradient(instance_type);

        // Sync instance-dependent gradient params.
        if (instance_type == InstanceType::kLinear) {
            auto* lg = static_cast<sksg::LinearGradient*>(fGradient.get());
            lg->setStartPoint(fStartPoint);
            lg->setEndPoint(fEndPoint);
        } else {
            SkASSERT(instance_type == InstanceType::kRadial);

            auto* rg = static_cast<sksg::RadialGradient*>(fGradient.get());
            rg->setStartCenter(fStartPoint);
            rg->setEndCenter(fStartPoint);
            rg->setEndRadius(SkPoint::Distance(fStartPoint, fEndPoint));
        }

        // TODO: blend, scatter
    }

    sk_sp<sksg::ShaderEffect> fRoot;
    sk_sp<sksg::Gradient>     fGradient;
    InstanceType              fInstanceType = InstanceType::kNone;
};

} // anonymous ns

sk_sp<sksg::RenderNode> EffectBuilder::attachGradientEffect(const skjson::ArrayValue& jprops,
                                                            sk_sp<sksg::RenderNode> layer) const {
    enum : size_t {
        kStartPoint_Index  = 0,
        kStartColor_Index  = 1,
        kEndPoint_Index    = 2,
        kEndColor_Index    = 3,
        kRampShape_Index   = 4,
        kRampScatter_Index = 5,
        kBlendRatio_Index  = 6,
    };

    auto adapter = sk_make_sp<GradientRampEffectAdapter>(std::move(layer));

    fBuilder->bindProperty<VectorValue>(GetPropValue(jprops, kStartPoint_Index), fScope,
        [adapter](const VectorValue& p0) {
            adapter->setStartPoint(ValueTraits<VectorValue>::As<SkPoint>(p0));
        });
    fBuilder->bindProperty<VectorValue>(GetPropValue(jprops, kEndPoint_Index), fScope,
        [adapter](const VectorValue& p1) {
            adapter->setEndPoint(ValueTraits<VectorValue>::As<SkPoint>(p1));
        });
    fBuilder->bindProperty<VectorValue>(GetPropValue(jprops, kStartColor_Index), fScope,
        [adapter](const VectorValue& c0) {
            adapter->setStartColor(ValueTraits<VectorValue>::As<SkColor>(c0));
        });
    fBuilder->bindProperty<VectorValue>(GetPropValue(jprops, kEndColor_Index), fScope,
        [adapter](const VectorValue& c1) {
            adapter->setEndColor(ValueTraits<VectorValue>::As<SkColor>(c1));
        });
    fBuilder->bindProperty<ScalarValue>(GetPropValue(jprops, kRampShape_Index), fScope,
        [adapter](const ScalarValue& shape) {
            adapter->setShape(shape);
        });
    fBuilder->bindProperty<ScalarValue>(GetPropValue(jprops, kBlendRatio_Index), fScope,
        [adapter](const ScalarValue& blend) {
            adapter->setBlend(blend);
        });
    fBuilder->bindProperty<ScalarValue>(GetPropValue(jprops, kRampScatter_Index), fScope,
        [adapter](const ScalarValue& scatter) {
            adapter->setScatter(scatter);
        });

    return adapter->root();
}

} // namespace internal
} // namespace skottie
