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

#ifndef SkottieKeyframeAnimator_DEFINED
#define SkottieKeyframeAnimator_DEFINED

#include "include/core/SkCubicMap.h"
#include "include/core/SkPoint.h"
#include "include/private/SkNoncopyable.h"
#include "modules/skottie/include/Skottie.h"
#include "modules/skottie/src/animator/Animator.h"

#include <vector>

namespace skjson {
class ArrayValue;
class ObjectValue;
class Value;
} // namespace skjson

namespace skottie::internal {

class AnimationBuilder;

struct Keyframe {
    // We can store scalar values inline; other types are stored externally,
    // and we track them by index.
    struct Value {
        enum class Type {
            kIndex,
            kScalar,
        };

        union {
            uint32_t idx;
            float    flt;
        };

        bool equals(const Value& other, Type ty) const {
            return ty == Type::kIndex
                ? idx == other.idx
                : flt == other.flt;
        }
    };

    float    t;
    Value    v;
    uint32_t mapping; // Encodes the value interpolation in [KFRec_n .. KFRec_n+1):
                      //   0 -> constant
                      //   1 -> linear
                      //   n -> cubic: cubic_mappers[n-2]

    inline static constexpr uint32_t kConstantMapping  = 0;
    inline static constexpr uint32_t kLinearMapping    = 1;
    inline static constexpr uint32_t kCubicIndexOffset = 2;
};

class KeyframeAnimator : public Animator {
public:
    ~KeyframeAnimator() override;

    bool isConstant() const {
        SkASSERT(!fKFs.empty());

        // parseKeyFrames() ensures we only keep a single frame for constant properties.
        return fKFs.size() == 1;
    }

protected:
    KeyframeAnimator(std::vector<Keyframe> kfs, std::vector<SkCubicMap> cms)
        : fKFs(std::move(kfs))
        , fCMs(std::move(cms)) {}

    struct LERPInfo {
        float           weight; // vrec0/vrec1 weight [0..1]
        Keyframe::Value vrec0, vrec1;
    };

    // Main entry point: |t| -> LERPInfo
    LERPInfo getLERPInfo(float t) const;

private:
    // Two sequential KFRecs determine how the value varies within [kf0 .. kf1)
    struct KFSegment {
        const Keyframe* kf0;
        const Keyframe* kf1;

        bool contains(float t) const {
            SkASSERT(!!kf0 == !!kf1);
            SkASSERT(!kf0 || kf1 == kf0 + 1);

            return kf0 && kf0->t <= t && t < kf1->t;
        }
    };

    // Find the KFSegment containing |t|.
    KFSegment find_segment(float t) const;

    // Given a |t| and a containing KFSegment, compute the local interpolation weight.
    float compute_weight(const KFSegment& seg, float t) const;

    const std::vector<Keyframe>   fKFs; // Keyframe records, one per AE/Lottie keyframe.
    const std::vector<SkCubicMap> fCMs; // Optional cubic mappers (Bezier interpolation).
    mutable KFSegment             fCurrentSegment = { nullptr, nullptr }; // Cached segment.
};

class AnimatorBuilder : public SkNoncopyable {
public:
    virtual ~AnimatorBuilder();

    virtual sk_sp<KeyframeAnimator> makeFromKeyframes(const AnimationBuilder&,
                                                      const skjson::ArrayValue&) = 0;

    virtual sk_sp<Animator> makeFromExpression(ExpressionManager&, const char*) = 0;

    virtual bool parseValue(const AnimationBuilder&, const skjson::Value&) const = 0;

protected:
    explicit AnimatorBuilder(Keyframe::Value::Type ty)
        : keyframe_type(ty) {}

    virtual bool parseKFValue(const AnimationBuilder&,
                              const skjson::ObjectValue&,
                              const skjson::Value&,
                              Keyframe::Value*) = 0;

    bool parseKeyframes(const AnimationBuilder&, const skjson::ArrayValue&);

    std::vector<Keyframe>   fKFs; // Keyframe records, one per AE/Lottie keyframe.
    std::vector<SkCubicMap> fCMs; // Optional cubic mappers (Bezier interpolation).

private:
    uint32_t parseMapping(const skjson::ObjectValue&);

    const Keyframe::Value::Type keyframe_type;

    // Track previous cubic map parameters (for deduping).
    SkPoint                     prev_c0 = { 0, 0 },
                                prev_c1 = { 0, 0 };
};

template <typename T>
T Lerp(const T& a, const T& b, float t) { return a + (b - a) * t; }

} // namespace skottie::internal

#endif // SkottieKeyframeAnimator_DEFINED
