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

#include "include/core/SkM44.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/layers/shapelayer/ShapeLayer.h"
#include "modules/sksg/include/SkSGGeometryEffect.h"
#include "src/core/SkGeometry.h"

#include <vector>

namespace skottie::internal {

namespace  {

static SkPoint lerp(const SkPoint& p0, const SkPoint& p1, SkScalar t) {
    return p0 + (p1 - p0) * t;
}

// Operates on the cubic representation of a shape.  Pulls vertices towards the shape center,
// and cubic control points away from the center.  The general shape center is the vertex average.
class PuckerBloatEffect final : public sksg::GeometryEffect {
public:
    explicit PuckerBloatEffect(sk_sp<sksg::GeometryNode> geo) : INHERITED({std::move(geo)}) {}

    // Fraction of the transition to center. I.e.
    //
    //     0 -> no effect
    //     1 -> vertices collapsed to center
    //
    // Negative values are allowed (inverse direction), as are extranormal values.
    SG_ATTRIBUTE(Amount, float, fAmount)

private:
    SkPath onRevalidateEffect(const sk_sp<GeometryNode>& geo) override {
        struct CubicInfo {
            SkPoint ctrl0, ctrl1, pt; // corresponding to SkPath::cubicTo() params, respectively.
        };

        const auto input = geo->asPath();
        if (SkScalarNearlyZero(fAmount)) {
            return input;
        }

        const auto input_bounds = input.computeTightBounds();
        const SkPoint center{input_bounds.centerX(), input_bounds.centerY()};

        SkPath path;

        SkPoint contour_start = {0, 0};
        std::vector<CubicInfo> cubics;

        auto commit_contour = [&]() {
            path.moveTo(lerp(contour_start, center, fAmount));
            for (const auto& c : cubics) {
                path.cubicTo(lerp(c.ctrl0, center, -fAmount),
                             lerp(c.ctrl1, center, -fAmount),
                             lerp(c.pt   , center,  fAmount));
            }
            path.close();

            cubics.clear();
        };

        // Normalize all verbs to cubic representation.
        SkPoint pts[4];
        SkPath::Verb verb;
        SkPath::Iter iter(input, true);
        while ((verb = iter.next(pts)) != SkPath::kDone_Verb) {
            switch (verb) {
                case SkPath::kMove_Verb:
                    commit_contour();
                    contour_start = pts[0];
                    break;
                case SkPath::kLine_Verb: {
                    // Empirically, straight lines are treated as cubics with control points
                    // located length/100 away from extremities.
                    static constexpr float kCtrlPosFraction = 1.f / 100;
                    const auto line_start = pts[0],
                               line_end   = pts[1];
                    cubics.push_back({
                            lerp(line_start, line_end,     kCtrlPosFraction),
                            lerp(line_start, line_end, 1 - kCtrlPosFraction),
                            line_end
                    });
                } break;
                case SkPath::kQuad_Verb:
                    SkConvertQuadToCubic(pts, pts);
                    cubics.push_back({pts[1], pts[2], pts[3]});
                    break;
                case SkPath::kConic_Verb: {
                    // We should only ever encounter conics from circles/ellipses.
                    SkASSERT(SkScalarNearlyEqual(iter.conicWeight(), SK_ScalarRoot2Over2));

                    // http://spencermortensen.com/articles/bezier-circle/
                    static constexpr float kCubicCircleCoeff = 1 - 0.551915024494f;

                    const auto conic_start = cubics.empty() ? contour_start
                                                            : cubics.back().pt,
                               conic_end   = pts[2];

                    cubics.push_back({
                        lerp(pts[1], conic_start, kCubicCircleCoeff),
                        lerp(pts[1], conic_end  , kCubicCircleCoeff),
                        conic_end
                    });
                } break;
                case SkPath::kCubic_Verb:
                    cubics.push_back({pts[1], pts[2], pts[3]});
                    break;
                case SkPath::kClose_Verb:
                    commit_contour();
                    break;
                default:
                    break;
            }
        }

        return path;
    }

    float fAmount = 0;

    using INHERITED = sksg::GeometryEffect;
};

class PuckerBloatAdapter final : public DiscardableAdapterBase<PuckerBloatAdapter,
                                                               PuckerBloatEffect> {
public:
    PuckerBloatAdapter(const skjson::ObjectValue& joffset,
                       const AnimationBuilder& abuilder,
                       sk_sp<sksg::GeometryNode> child)
        : INHERITED(sk_make_sp<PuckerBloatEffect>(std::move(child))) {
        this->bind(abuilder, joffset["a" ], fAmount);
    }

private:
    void onSync() override {
        // AE amount is percentage-based.
        this->node()->setAmount(fAmount / 100);
    }

    ScalarValue fAmount = 0;

    using INHERITED = DiscardableAdapterBase<PuckerBloatAdapter, PuckerBloatEffect>;
};

} // namespace

std::vector<sk_sp<sksg::GeometryNode>> ShapeBuilder::AttachPuckerBloatGeometryEffect(
        const skjson::ObjectValue& jround, const AnimationBuilder* abuilder,
        std::vector<sk_sp<sksg::GeometryNode>>&& geos) {
    std::vector<sk_sp<sksg::GeometryNode>> bloated;
    bloated.reserve(geos.size());

    for (auto& g : geos) {
        bloated.push_back(abuilder->attachDiscardableAdapter<PuckerBloatAdapter>
                                        (jround, *abuilder, std::move(g)));
    }

    return bloated;
}

} // namespace skottie::internal
