/*
 * 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/SkottieJson.h"
#include "modules/skottie/src/Transform.h"
#include "modules/sksg/include/SkSGOpacityEffect.h"
#include "modules/sksg/include/SkSGTransform.h"

namespace skottie {
namespace internal {

namespace  {

class TransformEffectAdapter final : public DiscardableAdapterBase<TransformEffectAdapter,
                                                                   sksg::OpacityEffect> {
public:
    TransformEffectAdapter(const AnimationBuilder& abuilder,
                           const skjson::ObjectValue* jopacity,
                           const skjson::ObjectValue* jscale_uniform,
                           const skjson::ObjectValue* jscale_width,
                           const skjson::ObjectValue* jscale_height,
                           sk_sp<TransformAdapter2D> tadapter,
                           sk_sp<sksg::RenderNode> child)
        : INHERITED(sksg::OpacityEffect::Make(std::move(child)))
        , fTransformAdapter(std::move(tadapter)) {
        this->bind(abuilder, jopacity      , fOpacity     );
        this->bind(abuilder, jscale_uniform, fUniformScale);
        this->bind(abuilder, jscale_width  , fScaleWidth  );
        this->bind(abuilder, jscale_height , fScaleHeight );

        this->attachDiscardableAdapter(fTransformAdapter);
    }

private:
    void onSync() override {
        this->node()->setOpacity(fOpacity * 0.01f);

        // In uniform mode, the scale is based solely in ScaleHeight.
        const auto scale = SkVector::Make(SkScalarRoundToInt(fUniformScale) ? fScaleHeight
                                                                            : fScaleWidth,
                                          fScaleHeight);

        // NB: this triggers an transform adapter -> SG sync.
        fTransformAdapter->setScale(scale);
    }

    const sk_sp<TransformAdapter2D> fTransformAdapter;

    ScalarValue fOpacity      = 100,
                fUniformScale =   0, // bool
                fScaleWidth   = 100,
                fScaleHeight  = 100;

    using INHERITED = DiscardableAdapterBase<TransformEffectAdapter, sksg::OpacityEffect>;
};

}  // namespace

sk_sp<sksg::RenderNode> EffectBuilder::attachTransformEffect(const skjson::ArrayValue& jprops,
                                                             sk_sp<sksg::RenderNode> layer) const {
    enum : size_t {
        kAnchorPoint_Index            =  0,
        kPosition_Index               =  1,
        kUniformScale_Index           =  2,
        kScaleHeight_Index            =  3,
        kScaleWidth_Index             =  4,
        kSkew_Index                   =  5,
        kSkewAxis_Index               =  6,
        kRotation_Index               =  7,
        kOpacity_Index                =  8,
        // kUseCompShutterAngle_Index =  9,
        // kShutterAngle_Index        = 10,
        // kSampling_Index            = 11,
    };

    auto transform_adapter = TransformAdapter2D::Make(*fBuilder,
                                                      GetPropValue(jprops, kAnchorPoint_Index),
                                                      GetPropValue(jprops, kPosition_Index),
                                                      nullptr, // scale is handled externally
                                                      GetPropValue(jprops, kRotation_Index),
                                                      GetPropValue(jprops, kSkew_Index),
                                                      GetPropValue(jprops, kSkewAxis_Index));
    if (!transform_adapter) {
        return nullptr;
    }

    auto transform_effect_node = sksg::TransformEffect::Make(std::move(layer),
                                                             transform_adapter->node());
    return fBuilder->attachDiscardableAdapter<TransformEffectAdapter>
            (*fBuilder,
             GetPropValue(jprops, kOpacity_Index),
             GetPropValue(jprops, kUniformScale_Index),
             GetPropValue(jprops, kScaleWidth_Index),
             GetPropValue(jprops, kScaleHeight_Index),
             std::move(transform_adapter),
             std::move(transform_effect_node)
             );
}

} // namespace internal
} // namespace skottie
