/*
 * 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/SkPoint.h"
#include "include/core/SkRefCnt.h"
#include "include/core/SkScalar.h"
#include "include/private/SkAssert.h"
#include "modules/skottie/src/SkottiePriv.h"
#include "modules/skottie/src/SkottieValue.h"
#include "modules/skottie/src/animator/Animator.h"
#include "modules/skottie/src/effects/Effects.h"
#include "modules/sksg/include/SkSGGradient.h"
#include "modules/sksg/include/SkSGRenderEffect.h"
#include "modules/sksg/include/SkSGRenderNode.h"

#include <cstddef>
#include <utility>

namespace skjson {
class ArrayValue;
}

namespace skottie {
namespace internal {

namespace  {

class GradientRampEffectAdapter final : public AnimatablePropertyContainer {
public:
    static sk_sp<GradientRampEffectAdapter> Make(const skjson::ArrayValue& jprops,
                                                 sk_sp<sksg::RenderNode> layer,
                                                 const AnimationBuilder* abuilder) {
        return sk_sp<GradientRampEffectAdapter>(new GradientRampEffectAdapter(jprops,
                                                                              std::move(layer),
                                                                              abuilder));
    }

    sk_sp<sksg::RenderNode> node() const { return fShaderEffect; }

private:
    GradientRampEffectAdapter(const skjson::ArrayValue& jprops,
                              sk_sp<sksg::RenderNode> layer,
                              const AnimationBuilder* abuilder)
        : fShaderEffect(sksg::ShaderEffect::Make(std::move(layer))) {
        enum : size_t {
             kStartPoint_Index = 0,
             kStartColor_Index = 1,
               kEndPoint_Index = 2,
               kEndColor_Index = 3,
              kRampShape_Index = 4,
            kRampScatter_Index = 5,
             kBlendRatio_Index = 6,
        };

        EffectBinder(jprops, *abuilder, this)
                .bind( kStartPoint_Index, fStartPoint)
                .bind( kStartColor_Index, fStartColor)
                .bind(   kEndPoint_Index, fEndPoint  )
                .bind(   kEndColor_Index, fEndColor  )
                .bind(  kRampShape_Index, fShape     )
                .bind(kRampScatter_Index, fScatter   )
                .bind( kBlendRatio_Index, fBlend     );
    }

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

    void onSync() override {
        // 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());

                fShaderEffect->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.
        const auto start_point = SkPoint{fStartPoint.x, fStartPoint.y},
                     end_point = SkPoint{  fEndPoint.x,   fEndPoint.y};
        if (instance_type == InstanceType::kLinear) {
            auto* lg = static_cast<sksg::LinearGradient*>(fGradient.get());
            lg->setStartPoint(start_point);
            lg->setEndPoint(end_point);
        } else {
            SkASSERT(instance_type == InstanceType::kRadial);

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

        // TODO: blend, scatter
    }

    const sk_sp<sksg::ShaderEffect> fShaderEffect;
    sk_sp<sksg::Gradient>           fGradient;

    InstanceType              fInstanceType = InstanceType::kNone;

    ColorValue  fStartColor,
                fEndColor;
    Vec2Value   fStartPoint = {0,0},
                fEndPoint   = {0,0};
    ScalarValue fBlend   = 0,
                fScatter = 0,
                fShape   = 0; // 1 -> linear, 7 -> radial (?!)
};

}  // namespace

sk_sp<sksg::RenderNode> EffectBuilder::attachGradientEffect(const skjson::ArrayValue& jprops,
                                                            sk_sp<sksg::RenderNode> layer) const {
    return fBuilder->attachDiscardableAdapter<GradientRampEffectAdapter>(jprops,
                                                                         std::move(layer),
                                                                         fBuilder);
}

} // namespace internal
} // namespace skottie
