/*
 * 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 "include/core/SkCanvas.h"
#include "include/effects/SkGradientShader.h"
#include "modules/skottie/src/Adapter.h"
#include "modules/skottie/src/SkottieValue.h"
#include "modules/sksg/include/SkSGRenderNode.h"
#include "src/utils/SkJSON.h"

#include <cmath>

namespace skottie {
namespace internal {

namespace  {

class RWipeRenderNode final : public sksg::CustomRenderNode {
public:
    explicit RWipeRenderNode(sk_sp<sksg::RenderNode> layer)
        : INHERITED({std::move(layer)}) {}

    SG_ATTRIBUTE(Completion, float  , fCompletion)
    SG_ATTRIBUTE(StartAngle, float  , fStartAngle)
    SG_ATTRIBUTE(WipeCenter, SkPoint, fWipeCenter)
    SG_ATTRIBUTE(Wipe      , float  , fWipe      )
    SG_ATTRIBUTE(Feather   , float  , fFeather   )

protected:
    const RenderNode* onNodeAt(const SkPoint&) const override { return nullptr; } // no hit-testing

    SkRect onRevalidate(sksg::InvalidationController* ic, const SkMatrix& ctm) override {
        SkASSERT(this->children().size() == 1ul);
        const auto content_bounds = this->children()[0]->revalidate(ic, ctm);

        if (fCompletion >= 100) {
            return SkRect::MakeEmpty();
        }

        if (fCompletion <= 0) {
            fMaskSigma  = 0;
            fMaskShader = nullptr;
        } else {
            fMaskSigma = std::max(fFeather, 0.0f) * kBlurSizeToSigma;

            const auto t = fCompletion * 0.01f;

            // Note: this could be simplified as a one-hard-stop gradient + local matrix
            // (to apply rotation).  Alas, local matrices are no longer supported in SkSG.
            SkColor c0 = 0x00000000,
                    c1 = 0xffffffff;
            auto sanitize_angle = [](float a) {
                a = std::fmod(a, 360);
                if (a < 0) {
                    a += 360;
                }
                return a;
            };

            auto a0 = sanitize_angle(fStartAngle - 90 + t * this->wipeAlignment()),
                 a1 = sanitize_angle(a0 + t * 360);
            if (a0 > a1) {
                std::swap(a0, a1);
                std::swap(c0, c1);
            }

            const SkColor grad_colors[] = { c1, c0, c0, c1 };
            const SkScalar   grad_pos[] = {  0,  0,  1,  1 };

            fMaskShader = SkGradientShader::MakeSweep(fWipeCenter.x(), fWipeCenter.y(),
                                                      grad_colors, grad_pos,
                                                      SK_ARRAY_COUNT(grad_colors),
                                                      SkTileMode::kClamp,
                                                      a0, a1, 0, nullptr);

            // Edge feather requires a real blur.
            if (fMaskSigma > 0) {
                // TODO: this feature is disabled ATM.
            }
        }

        return content_bounds;
    }

    void onRender(SkCanvas* canvas, const RenderContext* ctx) const override {
        if (fCompletion >= 100) {
            // Fully masked out.
            return;
        }

        const auto local_ctx = ScopedRenderContext(canvas, ctx)
                                    .modulateMaskShader(fMaskShader, canvas->getTotalMatrix());
        this->children()[0]->render(canvas, local_ctx);
    }

private:
    float wipeAlignment() const {
        switch (SkScalarRoundToInt(fWipe)) {
        case 1: return    0.0f; // Clockwise
        case 2: return -360.0f; // Counterclockwise
        case 3: return -180.0f; // Both/center
        default: break;
        }
        return 0.0f;
    }

    SkPoint fWipeCenter = { 0, 0 };
    float   fCompletion = 0,
            fStartAngle = 0,
            fWipe       = 0,
            fFeather    = 0;

    // Cached during revalidation.
    sk_sp<SkShader> fMaskShader;
    float           fMaskSigma; // edge feather/blur

    using INHERITED = sksg::CustomRenderNode;
};

class RadialWipeAdapter final : public DiscardableAdapterBase<RadialWipeAdapter, RWipeRenderNode> {
public:
    RadialWipeAdapter(const skjson::ArrayValue& jprops,
                      sk_sp<sksg::RenderNode> layer,
                      const AnimationBuilder& abuilder)
        : INHERITED(sk_make_sp<RWipeRenderNode>(std::move(layer))) {

        enum : size_t {
            kCompletion_Index = 0,
            kStartAngle_Index = 1,
            kWipeCenter_Index = 2,
                  kWipe_Index = 3,
               kFeather_Index = 4,
        };

        EffectBinder(jprops, abuilder, this)
            .bind(kCompletion_Index, fCompletion)
            .bind(kStartAngle_Index, fStartAngle)
            .bind(kWipeCenter_Index, fWipeCenter)
            .bind(      kWipe_Index, fWipe      )
            .bind(   kFeather_Index, fFeather   );
    }

private:
    void onSync() override {
        const auto& wiper = this->node();

        wiper->setCompletion(fCompletion);
        wiper->setStartAngle(fStartAngle);
        wiper->setWipeCenter({fWipeCenter.x, fWipeCenter.y});
        wiper->setWipe(fWipe);
        wiper->setFeather(fFeather);
    }

    Vec2Value   fWipeCenter = {0,0};
    ScalarValue fCompletion = 0,
                fStartAngle = 0,
                fWipe       = 0,
                fFeather    = 0;

    using INHERITED = DiscardableAdapterBase<RadialWipeAdapter, RWipeRenderNode>;
};

} // namespace

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

} // namespace internal
} // namespace skottie
