/*
 * 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 "modules/skottie/src/animator/VectorKeyframeAnimator.h"

#include "include/core/SkColor.h"
#include "include/core/SkCubicMap.h"
#include "include/core/SkM44.h"
#include "include/core/SkScalar.h"
#include "include/core/SkString.h"
#include "include/core/SkTypes.h"
#include "include/private/SkTFitsIn.h"
#include "include/private/SkTPin.h"
#include "include/private/SkTo.h"
#include "modules/jsonreader/SkJSONReader.h"
#include "modules/skottie/include/Skottie.h"
#include "modules/skottie/include/SlotManager.h"
#include "modules/skottie/src/SkottieJson.h"
#include "modules/skottie/src/SkottiePriv.h"
#include "modules/skottie/src/SkottieValue.h"
#include "modules/skottie/src/animator/Animator.h"
#include "src/core/SkSafeMath.h"
#include "src/core/SkVx.h"

#include <algorithm>
#include <cstdint>
#include <cstring>
#include <utility>

namespace skottie {

// Parses an array of exact size.
static bool parse_array(const skjson::ArrayValue* ja, float* a, size_t count) {
    if (!ja || ja->size() != count) {
        return false;
    }

    for (size_t i = 0; i < count; ++i) {
        if (!Parse((*ja)[i], a + i)) {
            return false;
        }
    }

    return true;
}

VectorValue::operator SkV3() const {
    // best effort to turn this into a 3D point
    return SkV3 {
        this->size() > 0 ? (*this)[0] : 0,
        this->size() > 1 ? (*this)[1] : 0,
        this->size() > 2 ? (*this)[2] : 0,
    };
}

ColorValue::operator SkColor() const {
    return static_cast<SkColor4f>(*this).toSkColor();
}

ColorValue::operator SkColor4f() const {
    // best effort to turn a vector into a color
    const auto r = this->size() > 0 ? SkTPin((*this)[0], 0.0f, 1.0f) : 0,
               g = this->size() > 1 ? SkTPin((*this)[1], 0.0f, 1.0f) : 0,
               b = this->size() > 2 ? SkTPin((*this)[2], 0.0f, 1.0f) : 0,
               a = this->size() > 3 ? SkTPin((*this)[3], 0.0f, 1.0f) : 1;

    return { r, g, b, a };
}

namespace internal {
namespace {

// Vector specialization - stores float vector values (of same length) in consolidated/contiguous
// storage.  Keyframe records hold the storage offset for each value:
//
// fStorage: [     vec0     ][     vec1     ] ... [     vecN     ]
//            <-  vec_len ->  <-  vec_len ->       <-  vec_len ->
//
//           ^               ^                    ^
// fKFs[]: .idx            .idx       ...       .idx
//
class VectorKeyframeAnimator final : public KeyframeAnimator {
public:
    VectorKeyframeAnimator(std::vector<Keyframe> kfs,
                           std::vector<SkCubicMap> cms,
                           std::vector<float> storage,
                           size_t vec_len,
                           std::vector<float>* target_value)
        : INHERITED(std::move(kfs), std::move(cms))
        , fStorage(std::move(storage))
        , fVecLen(vec_len)
        , fTarget(target_value) {

        // Resize the target value appropriately.
        fTarget->resize(fVecLen);
    }

private:
    StateChanged onSeek(float t) override {
        const auto& lerp_info = this->getLERPInfo(t);

        SkASSERT(lerp_info.vrec0.idx + fVecLen <= fStorage.size());
        SkASSERT(lerp_info.vrec1.idx + fVecLen <= fStorage.size());
        SkASSERT(fTarget->size() == fVecLen);

        const auto* v0  = fStorage.data() + lerp_info.vrec0.idx;
        const auto* v1  = fStorage.data() + lerp_info.vrec1.idx;
              auto* dst = fTarget->data();

        const auto is_constant = lerp_info.vrec0.equals(lerp_info.vrec1,
                                                        Keyframe::Value::Type::kIndex);
        if (is_constant) {
            if (0 != std::memcmp(dst, v0, fVecLen * sizeof(float))) {
                std::copy(v0, v0 + fVecLen, dst);
                return true;
            }
            return false;
        }

        size_t count = fVecLen;
        bool changed = false;

        while (count >= 4) {
            const auto old_val = skvx::float4::Load(dst),
                       new_val = Lerp(skvx::float4::Load(v0),
                                      skvx::float4::Load(v1),
                                      lerp_info.weight);

            changed |= any(new_val != old_val);
            new_val.store(dst);

            v0    += 4;
            v1    += 4;
            dst   += 4;
            count -= 4;
        }

        while (count-- > 0) {
            const auto new_val = Lerp(*v0++, *v1++, lerp_info.weight);

            changed |= (new_val != *dst);
            *dst++ = new_val;
        }

        return changed;
    }

    const std::vector<float> fStorage;
    const size_t             fVecLen;

    std::vector<float>*      fTarget;

    using INHERITED = KeyframeAnimator;
};

class VectorExpressionAnimator final : public Animator {
public:
    VectorExpressionAnimator(sk_sp<ExpressionEvaluator<std::vector<float>>> expression_evaluator,
        std::vector<float>* target_value)
        : fExpressionEvaluator(std::move(expression_evaluator))
        , fTarget(target_value) {}

private:

    StateChanged onSeek(float t) override {
        std::vector<float> result = fExpressionEvaluator->evaluate(t);
        bool changed = false;
        for (size_t i = 0; i < fTarget->size(); i++) {
            // Use 0 as a default if the result is too small.
            float val = i >= result.size() ? 0 : result[i];
            if (!SkScalarNearlyEqual(val, (*fTarget)[i])) {
                changed = true;
            }
            (*fTarget)[i] = val;
        }

        return changed;
    }

    sk_sp<ExpressionEvaluator<std::vector<float>>> fExpressionEvaluator;
    std::vector<float>* fTarget;
};
} // namespace

VectorAnimatorBuilder::VectorAnimatorBuilder(std::vector<float>* target,
                                                             VectorLenParser  parse_len,
                                                             VectorDataParser parse_data)
    : INHERITED(Keyframe::Value::Type::kIndex)
    , fParseLen(parse_len)
    , fParseData(parse_data)
    , fTarget(target) {}

sk_sp<KeyframeAnimator> VectorAnimatorBuilder::makeFromKeyframes(const AnimationBuilder& abuilder,
                                                            const skjson::ArrayValue& jkfs) {
    SkASSERT(jkfs.size() > 0);

    // peek at the first keyframe value to find our vector length
    const skjson::ObjectValue* jkf0 = jkfs[0];
    if (!jkf0 || !fParseLen((*jkf0)["s"], &fVecLen)) {
        return nullptr;
    }

    SkSafeMath safe;
    // total elements: vector length x number vectors
    const auto total_size = safe.mul(fVecLen, jkfs.size());

    // we must be able to store all offsets in Keyframe::Value::idx (uint32_t)
    if (!safe || !SkTFitsIn<uint32_t>(total_size)) {
        return nullptr;
    }
    fStorage.resize(total_size);

    if (!this->parseKeyframes(abuilder, jkfs)) {
        return nullptr;
    }

    // parseKFValue() might have stored fewer vectors thanks to tail-deduping.
    SkASSERT(fCurrentVec <= jkfs.size());
    fStorage.resize(fCurrentVec * fVecLen);
    fStorage.shrink_to_fit();

    return sk_sp<VectorKeyframeAnimator>(
                new VectorKeyframeAnimator(std::move(fKFs),
                                           std::move(fCMs),
                                           std::move(fStorage),
                                           fVecLen,
                                           fTarget));
}

sk_sp<Animator> VectorAnimatorBuilder::makeFromExpression(ExpressionManager& em, const char* expr) {
    sk_sp<ExpressionEvaluator<std::vector<SkScalar>>> expression_evaluator =
            em.createArrayExpressionEvaluator(expr);
    return sk_make_sp<VectorExpressionAnimator>(expression_evaluator, fTarget);
}

bool VectorAnimatorBuilder::parseValue(const AnimationBuilder&,
                                               const skjson::Value& jv) const {
    size_t vec_len;
    if (!this->fParseLen(jv, &vec_len)) {
        return false;
    }

    fTarget->resize(vec_len);
    return fParseData(jv, vec_len, fTarget->data());
}

bool VectorAnimatorBuilder::parseKFValue(const AnimationBuilder&,
                                                 const skjson::ObjectValue&,
                                                 const skjson::Value& jv,
                                                 Keyframe::Value* kfv) {
    auto offset = fCurrentVec * fVecLen;
    SkASSERT(offset + fVecLen <= fStorage.size());

    if (!fParseData(jv, fVecLen, fStorage.data() + offset)) {
        return false;
    }

    SkASSERT(!fCurrentVec || offset >= fVecLen);
    // compare with previous vector value
    if (fCurrentVec > 0 && !memcmp(fStorage.data() + offset,
                                   fStorage.data() + offset - fVecLen,
                                   fVecLen * sizeof(float))) {
        // repeating value -> use prev offset (dedupe)
        offset -= fVecLen;
    } else {
        // new value -> advance the current index
        fCurrentVec += 1;
    }

    // Keyframes record the storage-offset for a given vector value.
    kfv->idx = SkToU32(offset);

    return true;
}

template <>
bool AnimatablePropertyContainer::bind<VectorValue>(const AnimationBuilder& abuilder,
                                                    const skjson::ObjectValue* jprop,
                                                    VectorValue* v) {
    if (!jprop) {
        return false;
    }

    if (!ParseDefault<bool>((*jprop)["s"], false)) {
        // Regular (static or keyframed) vector value.
        VectorAnimatorBuilder builder(
                    v,
                    // Len parser.
                    [](const skjson::Value& jv, size_t* len) -> bool {
                        if (const skjson::ArrayValue* ja = jv) {
                            *len = ja->size();
                            return true;
                        }
                        return false;
                    },
                    // Data parser.
                    [](const skjson::Value& jv, size_t len, float* data) {
                        return parse_array(jv, data, len);
                    });

        return this->bindImpl(abuilder, jprop, builder);
    }

    // Separate-dimensions vector value: each component is animated independently.
    *v = { 0, 0, 0 };
    bool boundX = this->bind(abuilder, (*jprop)["x"], v->data() + 0);
    bool boundY = this->bind(abuilder, (*jprop)["y"], v->data() + 1);
    bool boundZ = this->bind(abuilder, (*jprop)["z"], v->data() + 2);
    return boundX || boundY || boundZ;
}

template <>
bool AnimatablePropertyContainer::bind<ColorValue>(const AnimationBuilder& abuilder,
                                                    const skjson::ObjectValue* jprop,
                                                    ColorValue* v) {
    if (const auto* sid = ParseSlotID(jprop)) {
        fHasSlotID = true;
        abuilder.fSlotManager->trackColorValue(SkString(sid->begin()), v, sk_ref_sp(this));
    }
    return this->bind(abuilder, jprop, static_cast<VectorValue*>(v));
}

} // namespace internal
} // namespace skottie
