/*
 * 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/KeyframeAnimator.h"

#include "include/private/SkTo.h"
#include "modules/jsonreader/SkJSONReader.h"
#include "modules/skottie/src/SkottieJson.h"

#include <cstddef>

#define DUMP_KF_RECORDS 0

namespace skottie::internal {

KeyframeAnimator::~KeyframeAnimator() = default;

KeyframeAnimator::LERPInfo KeyframeAnimator::getLERPInfo(float t) const {
    SkASSERT(!fKFs.empty());

    if (t <= fKFs.front().t) {
        // Constant/clamped segment.
        return { 0, fKFs.front().v, fKFs.front().v };
    }
    if (t >= fKFs.back().t) {
        // Constant/clamped segment.
        return { 0, fKFs.back().v, fKFs.back().v };
    }

    // Cache the current segment (most queries have good locality).
    if (!fCurrentSegment.contains(t)) {
        fCurrentSegment = this->find_segment(t);
    }
    SkASSERT(fCurrentSegment.contains(t));

    if (fCurrentSegment.kf0->mapping == Keyframe::kConstantMapping) {
        // Constant/hold segment.
        return { 0, fCurrentSegment.kf0->v, fCurrentSegment.kf0->v };
    }

    return {
        this->compute_weight(fCurrentSegment, t),
        fCurrentSegment.kf0->v,
        fCurrentSegment.kf1->v,
    };
}

KeyframeAnimator::KFSegment KeyframeAnimator::find_segment(float t) const {
    SkASSERT(fKFs.size() > 1);
    SkASSERT(t > fKFs.front().t);
    SkASSERT(t < fKFs.back().t);

    auto kf0 = &fKFs.front(),
         kf1 = &fKFs.back();

    // Binary-search, until we reduce to sequential keyframes.
    while (kf0 + 1 != kf1) {
        SkASSERT(kf0 < kf1);
        SkASSERT(kf0->t <= t && t < kf1->t);

        const auto mid_kf = kf0 + (kf1 - kf0) / 2;

        if (t >= mid_kf->t) {
            kf0 = mid_kf;
        } else {
            kf1 = mid_kf;
        }
    }

    return {kf0, kf1};
}

float KeyframeAnimator::compute_weight(const KFSegment &seg, float t) const {
    SkASSERT(seg.contains(t));

    // Linear weight.
    auto w = (t - seg.kf0->t) / (seg.kf1->t - seg.kf0->t);

    // Optional cubic mapper.
    if (seg.kf0->mapping >= Keyframe::kCubicIndexOffset) {
        const auto mapper_index = SkToSizeT(seg.kf0->mapping - Keyframe::kCubicIndexOffset);
        w = fCMs[mapper_index].computeYFromX(w);
    }

    return w;
}

AnimatorBuilder::~AnimatorBuilder() = default;

bool AnimatorBuilder::parseKeyframes(const AnimationBuilder& abuilder,
                                     const skjson::ArrayValue& jkfs) {
    // Keyframe format:
    //
    // [                        // array of
    //   {
    //     "t": <float>         // keyframe time
    //     "s": <T>             // keyframe value
    //     "h": <bool>          // optional constant/hold keyframe marker
    //     "i": [<float,float>] // optional "in" Bezier control point
    //     "o": [<float,float>] // optional "out" Bezier control point
    //   },
    //   ...
    // ]
    //
    // Legacy keyframe format:
    //
    // [                        // array of
    //   {
    //     "t": <float>         // keyframe time
    //     "s": <T>             // keyframe start value
    //     "e": <T>             // keyframe end value
    //     "h": <bool>          // optional constant/hold keyframe marker (constant mapping)
    //     "i": [<float,float>] // optional "in" Bezier control point (cubic mapping)
    //     "o": [<float,float>] // optional "out" Bezier control point (cubic mapping)
    //   },
    //   ...
    //   {
    //     "t": <float>         // last keyframe only specifies a t
    //                          // the value is prev. keyframe end value
    //   }
    // ]
    //
    // Note: the legacy format contains duplicates, as normal frames are contiguous:
    //       frame(n).e == frame(n+1).s

    const auto parse_value = [&](const skjson::ObjectValue& jkf, size_t i, Keyframe::Value* v) {
        auto parsed = this->parseKFValue(abuilder, jkf, jkf["s"], v);

        // A missing value is only OK for the last legacy KF
        // (where it is pulled from prev KF 'end' value).
        if (!parsed && i > 0 && i == jkfs.size() - 1) {
            const skjson::ObjectValue* prev_kf = jkfs[i - 1];
            SkASSERT(prev_kf);
            parsed = this->parseKFValue(abuilder, jkf, (*prev_kf)["e"], v);
        }

        return parsed;
    };

    bool constant_value = true;

    fKFs.reserve(jkfs.size());

    for (size_t i = 0; i < jkfs.size(); ++i) {
        const skjson::ObjectValue* jkf = jkfs[i];
        if (!jkf) {
            return false;
        }

        float t;
        if (!Parse<float>((*jkf)["t"], &t)) {
            return false;
        }

        Keyframe::Value v;
        if (!parse_value(*jkf, i, &v)) {
            return false;
        }

        if (i > 0) {
            auto& prev_kf = fKFs.back();

            // Ts must be monotonic.
            if (t < prev_kf.t) {
                return false;
            }

            // We can power-reduce the mapping of repeated values (implicitly constant).
            if (v.equals(prev_kf.v, keyframe_type)) {
                prev_kf.mapping = Keyframe::kConstantMapping;
            }
        }

        fKFs.push_back({t, v, this->parseMapping(*jkf)});

        constant_value = constant_value && (v.equals(fKFs.front().v, keyframe_type));
    }

    SkASSERT(fKFs.size() == jkfs.size());
    fCMs.shrink_to_fit();

    if (constant_value) {
        // When all keyframes hold the same value, we can discard all but one
        // (interpolation has no effect).
        fKFs.resize(1);
    }

#if(DUMP_KF_RECORDS)
    SkDEBUGF("Animator[%p], values: %lu, KF records: %zu\n",
             this, fKFs.back().v_idx + 1, fKFs.size());
    for (const auto& kf : fKFs) {
        SkDEBUGF("  { t: %1.3f, v_idx: %lu, mapping: %lu }\n", kf.t, kf.v_idx, kf.mapping);
    }
#endif
    return true;
}

uint32_t AnimatorBuilder::parseMapping(const skjson::ObjectValue& jkf) {
    if (ParseDefault(jkf["h"], false)) {
        return Keyframe::kConstantMapping;
    }

    SkPoint c0, c1;
    if (!Parse(jkf["o"], &c0) ||
        !Parse(jkf["i"], &c1) ||
        SkCubicMap::IsLinear(c0, c1)) {
        return Keyframe::kLinearMapping;
    }

    // De-dupe sequential cubic mappers.
    if (c0 != prev_c0 || c1 != prev_c1 || fCMs.empty()) {
        fCMs.emplace_back(c0, c1);
        prev_c0 = c0;
        prev_c1 = c1;
    }

    SkASSERT(!fCMs.empty());
    return SkToU32(fCMs.size()) - 1 + Keyframe::kCubicIndexOffset;
}

} // namespace skottie::internal
