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

#include "SkCubicMap.h"
#include "SkottieJson.h"
#include "SkottiePriv.h"
#include "SkottieValue.h"
#include "SkSGScene.h"
#include "SkString.h"

#include <memory>
#include <vector>

namespace skottie {
namespace internal {

namespace {

class KeyframeAnimatorBase : public sksg::Animator {
public:
    size_t count() const { return fRecs.size(); }

protected:
    KeyframeAnimatorBase() = default;

    struct KeyframeRec {
        float t0, t1;
        int   vidx0, vidx1, // v0/v1 indices
              cmidx;        // cubic map index

        bool contains(float t) const { return t0 <= t && t <= t1; }
        bool isConstant() const { return vidx0 == vidx1; }
        bool isValid() const {
            SkASSERT(t0 <= t1);
            // Constant frames don't need/use t1 and vidx1.
            return t0 < t1 || this->isConstant();
        }
    };

    const KeyframeRec& frame(float t) {
        if (!fCachedRec || !fCachedRec->contains(t)) {
            fCachedRec = findFrame(t);
        }
        return *fCachedRec;
    }

    float localT(const KeyframeRec& rec, float t) const {
        SkASSERT(rec.isValid());
        SkASSERT(!rec.isConstant());
        SkASSERT(t > rec.t0 && t < rec.t1);

        auto lt = (t - rec.t0) / (rec.t1 - rec.t0);

        return rec.cmidx < 0
            ? lt
            : SkTPin(fCubicMaps[rec.cmidx].computeYFromX(lt), 0.0f, 1.0f);
    }

    virtual int parseValue(const skjson::Value&, const AnimationBuilder* abuilder) = 0;

    void parseKeyFrames(const skjson::ArrayValue& jframes, const AnimationBuilder* abuilder) {
        for (const skjson::ObjectValue* jframe : jframes) {
            if (!jframe) continue;

            float t0;
            if (!Parse<float>((*jframe)["t"], &t0))
                continue;

            if (!fRecs.empty()) {
                if (fRecs.back().t1 >= t0) {
                    abuilder->log(Logger::Level::kWarning, nullptr,
                                  "Ignoring out-of-order key frame (t:%f < t:%f).",
                                  t0, fRecs.back().t1);
                    continue;
                }
                // Back-fill t1 in prev interval.  Note: we do this even if we end up discarding
                // the current interval (to support "t"-only final frames).
                fRecs.back().t1 = t0;
            }

            // Required start value.
            const auto v0_idx = this->parseValue((*jframe)["s"], abuilder);
            if (v0_idx < 0)
                continue;

            // Optional end value.
            const auto v1_idx = this->parseValue((*jframe)["e"], abuilder);
            if (v1_idx < 0) {
                // Constant keyframe.
                fRecs.push_back({t0, t0, v0_idx, v0_idx, -1 });
                continue;
            }

            // default is linear lerp
            static constexpr SkPoint kDefaultC0 = { 0, 0 },
                                     kDefaultC1 = { 1, 1 };
            const auto c0 = ParseDefault<SkPoint>((*jframe)["i"], kDefaultC0),
                       c1 = ParseDefault<SkPoint>((*jframe)["o"], kDefaultC1);

            int cm_idx = -1;
            if (c0 != kDefaultC0 || c1 != kDefaultC1) {
                // TODO: is it worth de-duping these?
                cm_idx = SkToInt(fCubicMaps.size());
                fCubicMaps.emplace_back();
                // TODO: why do we have to plug these inverted?
                fCubicMaps.back().setPts(c1, c0);
            }

            fRecs.push_back({t0, t0, v0_idx, v1_idx, cm_idx });
        }

        // If we couldn't determine a valid t1 for the last frame, discard it.
        if (!fRecs.empty() && !fRecs.back().isValid()) {
            fRecs.pop_back();
        }

        fRecs.shrink_to_fit();
        fCubicMaps.shrink_to_fit();

        SkASSERT(fRecs.empty() || fRecs.back().isValid());
    }

    void reserve(size_t frame_count) {
        fRecs.reserve(frame_count);
        fCubicMaps.reserve(frame_count);
    }

private:
    const KeyframeRec* findFrame(float t) const {
        SkASSERT(!fRecs.empty());

        auto f0 = &fRecs.front(),
             f1 = &fRecs.back();

        SkASSERT(f0->isValid());
        SkASSERT(f1->isValid());

        if (t < f0->t0) {
            return f0;
        }

        if (t > f1->t1) {
            return f1;
        }

        while (f0 != f1) {
            SkASSERT(f0 < f1);
            SkASSERT(t >= f0->t0 && t <= f1->t1);

            const auto f = f0 + (f1 - f0) / 2;
            SkASSERT(f->isValid());

            if (t > f->t1) {
                f0 = f + 1;
            } else {
                f1 = f;
            }
        }

        SkASSERT(f0 == f1);
        SkASSERT(f0->contains(t));

        return f0;
    }

    std::vector<KeyframeRec> fRecs;
    std::vector<SkCubicMap>  fCubicMaps;
    const KeyframeRec*       fCachedRec = nullptr;

    using INHERITED = sksg::Animator;
};

template <typename T>
class KeyframeAnimator final : public KeyframeAnimatorBase {
public:
    static std::unique_ptr<KeyframeAnimator> Make(const skjson::ArrayValue* jv,
                                                  const AnimationBuilder* abuilder,
                                                  std::function<void(const T&)>&& apply) {
        if (!jv) return nullptr;

        std::unique_ptr<KeyframeAnimator> animator(
            new KeyframeAnimator(*jv, abuilder, std::move(apply)));
        if (!animator->count())
            return nullptr;

        return animator;
    }

protected:
    void onTick(float t) override {
        fApplyFunc(*this->eval(this->frame(t), t, &fScratch));
    }

private:
    KeyframeAnimator(const skjson::ArrayValue& jframes,
                     const AnimationBuilder* abuilder,
                     std::function<void(const T&)>&& apply)
        : fApplyFunc(std::move(apply)) {
        // Generally, each keyframe holds two values (start, end) and a cubic mapper. Except
        // the last frame, which only holds a marker timestamp.  Then, the values series is
        // contiguous (keyframe[i].end == keyframe[i + 1].start), and we dedupe them.
        //   => we'll store (keyframes.size) values and (keyframe.size - 1) recs and cubic maps.
        fVs.reserve(jframes.size());
        this->reserve(SkTMax<size_t>(jframes.size(), 1) - 1);

        this->parseKeyFrames(jframes, abuilder);

        fVs.shrink_to_fit();
    }

    int parseValue(const skjson::Value& jv, const AnimationBuilder* abuilder) override {
        T val;
        if (!ValueTraits<T>::FromJSON(jv, abuilder, &val) ||
            (!fVs.empty() && !ValueTraits<T>::CanLerp(val, fVs.back()))) {
            return -1;
        }

        // TODO: full deduping?
        if (fVs.empty() || val != fVs.back()) {
            fVs.push_back(std::move(val));
        }
        return SkToInt(fVs.size()) - 1;
    }

    const T* eval(const KeyframeRec& rec, float t, T* v) const {
        SkASSERT(rec.isValid());
        if (rec.isConstant() || t <= rec.t0) {
            return &fVs[rec.vidx0];
        } else if (t >= rec.t1) {
            return &fVs[rec.vidx1];
        }

        const auto lt = this->localT(rec, t);
        const auto& v0 = fVs[rec.vidx0];
        const auto& v1 = fVs[rec.vidx1];
        ValueTraits<T>::Lerp(v0, v1, lt, v);

        return v;
    }

    const std::function<void(const T&)> fApplyFunc;
    std::vector<T>                      fVs;

    // LERP storage: we use this to temporarily store interpolation results.
    // Alternatively, the temp result could live on the stack -- but for vector values that would
    // involve dynamic allocations on each tick.  This a trade-off to avoid allocator pressure
    // during animation.
    T                                   fScratch; // lerp storage

    using INHERITED = KeyframeAnimatorBase;
};

template <typename T>
static inline bool BindPropertyImpl(const skjson::ObjectValue* jprop,
                                    const AnimationBuilder* abuilder,
                                    AnimatorScope* ascope,
                                    std::function<void(const T&)>&& apply,
                                    const T* noop = nullptr) {
    if (!jprop) return false;

    const auto& jpropA = (*jprop)["a"];
    const auto& jpropK = (*jprop)["k"];

    if (!(*jprop)["x"].is<skjson::NullValue>()) {
        abuilder->log(Logger::Level::kWarning, nullptr, "Unsupported expression.");
    }

    // Older Json versions don't have an "a" animation marker.
    // For those, we attempt to parse both ways.
    if (!ParseDefault<bool>(jpropA, false)) {
        T val;
        if (ValueTraits<T>::FromJSON(jpropK, abuilder, &val)) {
            // Static property.
            if (noop && val == *noop)
                return false;

            apply(val);
            return true;
        }

        if (!jpropA.is<skjson::NullValue>()) {
            abuilder->log(Logger::Level::kError, jprop,
                          "Could not parse (explicit) static property.");
            return false;
        }
    }

    // Keyframe property.
    auto animator = KeyframeAnimator<T>::Make(jpropK, abuilder, std::move(apply));

    if (!animator) {
        abuilder->log(Logger::Level::kError, jprop, "Could not parse keyframed property.");
        return false;
    }

    ascope->push_back(std::move(animator));

    return true;
}

class SplitPointAnimator final : public sksg::Animator {
public:
    static std::unique_ptr<SplitPointAnimator> Make(const skjson::ObjectValue* jprop,
                                                    const AnimationBuilder* abuilder,
                                                    std::function<void(const VectorValue&)>&& apply,
                                                    const VectorValue*) {
        if (!jprop) return nullptr;

        std::unique_ptr<SplitPointAnimator> split_animator(
            new SplitPointAnimator(std::move(apply)));

        // This raw pointer is captured in lambdas below. But the lambdas are owned by
        // the object itself, so the scope is bound to the life time of the object.
        auto* split_animator_ptr = split_animator.get();

        if (!BindPropertyImpl<ScalarValue>((*jprop)["x"], abuilder, &split_animator->fAnimators,
                [split_animator_ptr](const ScalarValue& x) { split_animator_ptr->setX(x); }) ||
            !BindPropertyImpl<ScalarValue>((*jprop)["y"], abuilder, &split_animator->fAnimators,
                [split_animator_ptr](const ScalarValue& y) { split_animator_ptr->setY(y); })) {
            abuilder->log(Logger::Level::kError, jprop, "Could not parse split property.");
            return nullptr;
        }

        if (split_animator->fAnimators.empty()) {
            // Static split property: commit the (buffered) value and discard.
            split_animator->onTick(0);
            return nullptr;
        }

        return split_animator;
    }

    void onTick(float t) override {
        for (const auto& animator : fAnimators) {
            animator->tick(t);
        }

        const VectorValue vec = { fX, fY };
        fApplyFunc(vec);
    }

    void setX(const ScalarValue& x) { fX = x; }
    void setY(const ScalarValue& y) { fY = y; }

private:
    explicit SplitPointAnimator(std::function<void(const VectorValue&)>&& apply)
        : fApplyFunc(std::move(apply)) {}

    const std::function<void(const VectorValue&)> fApplyFunc;
    sksg::AnimatorList                            fAnimators;

    ScalarValue                                   fX = 0,
                                                  fY = 0;

    using INHERITED = sksg::Animator;
};

bool BindSplitPositionProperty(const skjson::Value& jv,
                               const AnimationBuilder* abuilder,
                               AnimatorScope* ascope,
                               std::function<void(const VectorValue&)>&& apply,
                               const VectorValue* noop) {
    if (auto split_animator = SplitPointAnimator::Make(jv, abuilder, std::move(apply), noop)) {
        ascope->push_back(std::unique_ptr<sksg::Animator>(split_animator.release()));
        return true;
    }

    return false;
}

} // namespace

template <>
bool AnimationBuilder::bindProperty(const skjson::Value& jv,
                  AnimatorScope* ascope,
                  std::function<void(const ScalarValue&)>&& apply,
                  const ScalarValue* noop) const {
    return BindPropertyImpl(jv, this, ascope, std::move(apply), noop);
}

template <>
bool AnimationBuilder::bindProperty(const skjson::Value& jv,
                  AnimatorScope* ascope,
                  std::function<void(const VectorValue&)>&& apply,
                  const VectorValue* noop) const {
    if (!jv.is<skjson::ObjectValue>())
        return false;

    return ParseDefault<bool>(jv.as<skjson::ObjectValue>()["s"], false)
        ? BindSplitPositionProperty(jv, this, ascope, std::move(apply), noop)
        : BindPropertyImpl(jv, this, ascope, std::move(apply), noop);
}

template <>
bool AnimationBuilder::bindProperty(const skjson::Value& jv,
                  AnimatorScope* ascope,
                  std::function<void(const ShapeValue&)>&& apply,
                  const ShapeValue* noop) const {
    return BindPropertyImpl(jv, this, ascope, std::move(apply), noop);
}

template <>
bool AnimationBuilder::bindProperty(const skjson::Value& jv,
                  AnimatorScope* ascope,
                  std::function<void(const TextValue&)>&& apply,
                  const TextValue* noop) const {
    return BindPropertyImpl(jv, this, ascope, std::move(apply), noop);
}

} // namespace internal
} // namespace skottie
