/*
 * Copyright 2020 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/SkCanvas.h"
#include "include/core/SkM44.h"
#include "include/core/SkMatrix.h"
#include "include/core/SkPaint.h"
#include "include/core/SkPicture.h"
#include "include/core/SkPictureRecorder.h"
#include "include/core/SkRect.h"
#include "include/core/SkRefCnt.h"
#include "include/core/SkSamplingOptions.h"
#include "include/core/SkScalar.h"
#include "include/core/SkShader.h"
#include "include/core/SkSize.h"
#include "include/core/SkString.h"
#include "include/core/SkTileMode.h"
#include "include/effects/SkRuntimeEffect.h"
#include "include/private/SkAssert.h"
#include "modules/jsonreader/SkJSONReader.h"
#include "modules/skottie/src/Adapter.h"
#include "modules/skottie/src/SkottieJson.h"
#include "modules/skottie/src/SkottiePriv.h"
#include "modules/skottie/src/SkottieValue.h"
#include "modules/skottie/src/effects/Effects.h"
#include "modules/sksg/include/SkSGNode.h"
#include "modules/sksg/include/SkSGRenderNode.h"
#include "src/core/SkColorData.h"

#include <algorithm>
#include <array>
#include <cmath>
#include <cstdio>
#include <utility>
#include <vector>

struct SkPoint;

namespace sksg {
class InvalidationController;
}

namespace skottie::internal {
namespace {

// AE's displacement map effect [1] is somewhat similar to SVG's feDisplacementMap [2].  Main
// differences:
//
//   - more selector options: full/half/off, luminance, hue/saturation/lightness
//   - the scale factor is anisotropic (independent x/y values)
//   - displacement coverage is restricted to non-transparent source for some selectors
//     (specifically: r, g, b, h, s, l).
//
// [1] https://helpx.adobe.com/after-effects/using/distort-effects.html#displacement_map_effect
// [2] https://www.w3.org/TR/SVG11/filters.html#feDisplacementMapElement

// |selector_matrix| and |selector_offset| are set up to select and scale the x/y displacement
// in R/G, and the x/y coverage modulation in B/A.
static constexpr char gDisplacementSkSL[] =
    "uniform shader child;"
    "uniform shader displ;"

    "uniform half4x4 selector_matrix;"
    "uniform half4   selector_offset;"

    "half4 main(float2 xy) {"
        "half4 d = displ.eval(xy);"

        "d = selector_matrix*unpremul(d) + selector_offset;"

        "return child.eval(xy + d.xy*d.zw);"
   "}"
;

static sk_sp<SkRuntimeEffect> displacement_effect_singleton() {
    static const SkRuntimeEffect* effect =
            SkRuntimeEffect::MakeForShader(SkString(gDisplacementSkSL)).effect.release();
    if (0 && !effect) {
        auto err = SkRuntimeEffect::MakeForShader(SkString(gDisplacementSkSL)).errorText;
        printf("!!! %s\n", err.c_str());
    }
    SkASSERT(effect);

    return sk_ref_sp(effect);
}

class DisplacementNode final : public sksg::CustomRenderNode {
public:
    ~DisplacementNode() override {
        this->unobserveInval(fDisplSource);
    }

    static sk_sp<DisplacementNode> Make(sk_sp<RenderNode> child,
                                        const SkSize& child_size,
                                        sk_sp<RenderNode> displ,
                                        const SkSize& displ_size) {
        if (!child || !displ) {
            return nullptr;
        }

        return sk_sp<DisplacementNode>(new DisplacementNode(std::move(child), child_size,
                                                            std::move(displ), displ_size));
    }

    enum class Pos : unsigned {
        kCenter,
        kStretch,
        kTile,

        kLast = kTile,
    };

    enum class Selector : unsigned {
        kR,
        kG,
        kB,
        kA,
        kLuminance,
        kHue,
        kLightness,
        kSaturation,
        kFull,
        kHalf,
        kOff,

        kLast = kOff,
    };

    SG_ATTRIBUTE(Scale        , SkV2      , fScale         )
    SG_ATTRIBUTE(ChildTileMode, SkTileMode, fChildTileMode )
    SG_ATTRIBUTE(Pos          , Pos       , fPos           )
    SG_ATTRIBUTE(XSelector    , Selector  , fXSelector     )
    SG_ATTRIBUTE(YSelector    , Selector  , fYSelector     )
    SG_ATTRIBUTE(ExpandBounds , bool      , fExpandBounds  )

private:
    DisplacementNode(sk_sp<RenderNode> child, const SkSize& child_size,
                     sk_sp<RenderNode> displ, const SkSize& displ_size)
        : INHERITED({std::move(child)})
        , fDisplSource(std::move(displ))
        , fDisplSize(displ_size)
        , fChildSize(child_size)
    {
        this->observeInval(fDisplSource);
    }

    struct SelectorCoeffs {
        float dr, dg, db, da, d_offset,  // displacement contribution
              c_scale, c_offset;         // coverage as a function of alpha
    };

    static SelectorCoeffs Coeffs(Selector sel) {
        // D = displacement input
        // C = displacement coverage
        static constexpr auto gCoeffs = std::to_array<SelectorCoeffs>({
                SelectorCoeffs{ 1,0,0,0,0,   1,0 }, // kR: D = r, C = a
                SelectorCoeffs{ 0,1,0,0,0,   1,0 }, // kG: D = g, C = a
                SelectorCoeffs{ 0,0,1,0,0,   1,0 }, // kB: D = b, C = a
                SelectorCoeffs{ 0,0,0,1,0,   0,1 }, // kA: D = a, C = 1.0
                SelectorCoeffs{ SK_LUM_COEFF_R, SK_LUM_COEFF_G, SK_LUM_COEFF_B, 0, 0, 1, 0},
                                                    // kLuminance: D = lum(rgb), C = a
                SelectorCoeffs{ 1,0,0,0,0,   0,1 }, // kH: D = h, C = 1.0   (HSLA)
                SelectorCoeffs{ 0,1,0,0,0,   0,1 }, // kL: D = l, C = 1.0   (HSLA)
                SelectorCoeffs{ 0,0,1,0,0,   0,1 }, // kS: D = s, C = 1.0   (HSLA)
                SelectorCoeffs{ 0,0,0,0,1,   0,1 }, // kFull: D = 1.0, C = 1.0
                SelectorCoeffs{ 0,0,0,0,.5f, 0,1 }, // kHalf: D = 0.5, C = 1.0
                SelectorCoeffs{ 0,0,0,0,0,   0,1 }, // kOff:  D = 0.0, C = 1.0
        });

        const auto i = static_cast<size_t>(sel);
        SkASSERT(i < std::size(gCoeffs));

        return gCoeffs[i];
    }

    static bool IsConst(Selector s) {
        return s == Selector::kFull
            || s == Selector::kHalf
            || s == Selector::kOff;
    }

    sk_sp<SkShader> buildEffectShader(sksg::InvalidationController* ic, const SkMatrix& ctm) {
        // AE quirk: combining two const/generated modes does not displace - we need at
        // least one non-const selector to trigger the effect.  *shrug*
        if ((IsConst(fXSelector) && IsConst(fYSelector)) ||
            (SkScalarNearlyZero(fScale.x) && SkScalarNearlyZero(fScale.y))) {
            return nullptr;
        }

        auto get_content_picture = [](const sk_sp<sksg::RenderNode>& node,
                                      sksg::InvalidationController* ic, const SkMatrix& ctm) {
            if (!node) {
                return sk_sp<SkPicture>(nullptr);
            }

            const auto bounds = node->revalidate(ic, ctm);

            SkPictureRecorder recorder;
            node->render(recorder.beginRecording(bounds));
            return recorder.finishRecordingAsPicture();
        };

        const auto child_content = get_content_picture(this->children()[0], ic, ctm),
                   displ_content = get_content_picture(fDisplSource, ic, ctm);
        if (!child_content || !displ_content) {
            return nullptr;
        }

        const auto child_tile = SkRect::MakeSize(fChildSize);
        auto child_shader = child_content->makeShader(fChildTileMode,
                                                      fChildTileMode,
                                                      SkFilterMode::kLinear,
                                                      nullptr,
                                                      &child_tile);

        const auto displ_tile   = SkRect::MakeSize(fDisplSize);
        const auto displ_mode   = this->displacementTileMode();
        const auto displ_matrix = this->displacementMatrix();
        auto displ_shader = displ_content->makeShader(displ_mode,
                                                      displ_mode,
                                                      SkFilterMode::kLinear,
                                                      &displ_matrix,
                                                      &displ_tile);

        SkRuntimeShaderBuilder builder(displacement_effect_singleton());
        builder.child("child") = std::move(child_shader);
        builder.child("displ") = std::move(displ_shader);

        const auto xc = Coeffs(fXSelector),
                   yc = Coeffs(fYSelector);

        const auto s = fScale * 2;

        const float selector_m[] = {
            xc.dr*s.x, yc.dr*s.y,          0,          0,
            xc.dg*s.x, yc.dg*s.y,          0,          0,
            xc.db*s.x, yc.db*s.y,          0,          0,
            xc.da*s.x, yc.da*s.y, xc.c_scale, yc.c_scale,

            //  │          │               │           └────  A -> vertical modulation
            //  │          │               └────────────────  B -> horizontal modulation
            //  │          └────────────────────────────────  G -> vertical displacement
            //  └───────────────────────────────────────────  R -> horizontal displacement
        };
        const float selector_o[] = {
            (xc.d_offset - .5f) * s.x,
            (yc.d_offset - .5f) * s.y,
                          xc.c_offset,
                          yc.c_offset,
        };

        builder.uniform("selector_matrix") = selector_m;
        builder.uniform("selector_offset") = selector_o;

        // TODO: RGB->HSL stage
        return builder.makeShader();
    }

    SkRect onRevalidate(sksg::InvalidationController* ic, const SkMatrix& ctm) override {
        fEffectShader = this->buildEffectShader(ic, ctm);

        auto bounds = this->children()[0]->revalidate(ic, ctm);
        if (fExpandBounds) {
            // Expand the bounds to accommodate max displacement (which is |fScale|).
            bounds.outset(std::abs(fScale.x), std::abs(fScale.y));
        }

        return bounds;
    }

    void onRender(SkCanvas* canvas, const RenderContext* ctx) const override {
        if (!fEffectShader) {
            // no displacement effect - just render the content
            this->children()[0]->render(canvas, ctx);
            return;
        }

        auto local_ctx = ScopedRenderContext(canvas, ctx).setIsolation(this->bounds(),
                                                                       canvas->getTotalMatrix(),
                                                                       true);
        SkPaint shader_paint;
        shader_paint.setShader(fEffectShader);

        canvas->drawRect(this->bounds(), shader_paint);
    }

    SkTileMode displacementTileMode() const {
        return fPos == Pos::kTile
                ? SkTileMode::kRepeat
                : SkTileMode::kClamp;
    }

    SkMatrix displacementMatrix() const {
        switch (fPos) {
            case Pos::kCenter:  return SkMatrix::Translate(
                                    (fChildSize.fWidth  - fDisplSize.fWidth ) / 2,
                                    (fChildSize.fHeight - fDisplSize.fHeight) / 2);
            case Pos::kStretch: return SkMatrix::Scale(
                                    fChildSize.fWidth  / fDisplSize.fWidth,
                                    fChildSize.fHeight / fDisplSize.fHeight);
            case Pos::kTile:    return SkMatrix::I();
        }
        SkUNREACHABLE;
    }

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

    const sk_sp<sksg::RenderNode> fDisplSource;
    const SkSize                  fDisplSize,
                                  fChildSize;

    // Cached top-level shader
    sk_sp<SkShader>        fEffectShader;

    SkV2                   fScale          = { 0, 0 };
    SkTileMode             fChildTileMode  = SkTileMode::kDecal;
    Pos                    fPos            = Pos::kCenter;
    Selector               fXSelector      = Selector::kR,
                           fYSelector      = Selector::kR;
    bool                   fExpandBounds   = false;

    using INHERITED = sksg::CustomRenderNode;
};

class DisplacementMapAdapter final : public DiscardableAdapterBase<DisplacementMapAdapter,
                                                                   DisplacementNode> {
public:
    DisplacementMapAdapter(const skjson::ArrayValue& jprops,
                           const AnimationBuilder* abuilder,
                           sk_sp<DisplacementNode> node)
        : INHERITED(std::move(node)) {
        EffectBinder(jprops, *abuilder, this)
                .bind(kUseForHorizontal_Index, fHorizontalSelector)
                .bind(kMaxHorizontal_Index   , fMaxHorizontal     )
                .bind(kUseForVertical_Index  , fVerticalSelector  )
                .bind(kMaxVertical_Index     , fMaxVertical       )
                .bind(kMapBehavior_Index     , fMapBehavior       )
                .bind(kEdgeBehavior_Index    , fEdgeBehavior      )
                .bind(kExpandOutput_Index    , fExpandOutput      );
    }

    static EffectBuilder::LayerContent GetDisplacementSource(
            const skjson::ArrayValue& jprops,
            const EffectBuilder* ebuilder) {

        if (const skjson::ObjectValue* jv = EffectBuilder::GetPropValue(jprops, kMapLayer_Index)) {
            return ebuilder->getLayerContent(ParseDefault((*jv)["k"], -1));
        }

        return { nullptr, {0,0} };
    }

private:
    enum : size_t {
        kMapLayer_Index         = 0,
        kUseForHorizontal_Index = 1,
        kMaxHorizontal_Index    = 2,
        kUseForVertical_Index   = 3,
        kMaxVertical_Index      = 4,
        kMapBehavior_Index      = 5,
        kEdgeBehavior_Index     = 6,
        kExpandOutput_Index     = 7,
    };

    template <typename E>
    E ToEnum(float v) {
        // map one-based float "enums" to real enum types
        const auto uv = std::min(static_cast<unsigned>(v) - 1,
                                 static_cast<unsigned>(E::kLast));

        return static_cast<E>(uv);
    }

    void onSync() override {
        if (!this->node()) {
            return;
        }

        this->node()->setScale({fMaxHorizontal, fMaxVertical});
        this->node()->setChildTileMode(fEdgeBehavior != 0 ? SkTileMode::kRepeat
                                                          : SkTileMode::kDecal);

        this->node()->setPos(ToEnum<DisplacementNode::Pos>(fMapBehavior));
        this->node()->setXSelector(ToEnum<DisplacementNode::Selector>(fHorizontalSelector));
        this->node()->setYSelector(ToEnum<DisplacementNode::Selector>(fVerticalSelector));
        this->node()->setExpandBounds(fExpandOutput != 0);
    }

    ScalarValue  fHorizontalSelector = 0,
                 fVerticalSelector   = 0,
                 fMaxHorizontal      = 0,
                 fMaxVertical        = 0,
                 fMapBehavior        = 0,
                 fEdgeBehavior       = 0,
                 fExpandOutput       = 0;

    using INHERITED = DiscardableAdapterBase<DisplacementMapAdapter, DisplacementNode>;
};

} // namespace

sk_sp<sksg::RenderNode> EffectBuilder::attachDisplacementMapEffect(
        const skjson::ArrayValue& jprops, sk_sp<sksg::RenderNode> layer) const {
    const LayerContent displ = DisplacementMapAdapter::GetDisplacementSource(jprops, this);

    auto displ_node = DisplacementNode::Make(layer,
                                             fLayerSize,
                                             std::move(displ.fContent),
                                             displ.fSize);

    if (!displ_node) {
        return layer;
    }

    return fBuilder->attachDiscardableAdapter<DisplacementMapAdapter>(jprops,
                                                                      fBuilder,
                                                                      std::move(displ_node));
}

} // namespace skottie::internal
