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

#include "modules/skottie/src/SkottieJson.h"

#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) {
        SkASSERT(seg.kf0->v != seg.kf1->v);
        const auto mapper_index = SkToSizeT(seg.kf0->mapping - Keyframe::kCubicIndexOffset);
        w = fCMs[mapper_index].computeYFromX(w);
    }

    return w;
}

KeyframeAnimatorBuilder::~KeyframeAnimatorBuilder() = default;

bool KeyframeAnimatorBuilder::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 strictly monotonic.
            if (t <= prev_kf.t) {
                return false;
            }

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

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

        constant_value = constant_value && (v == fKFs.front().v);
    }

    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 KeyframeAnimatorBuilder::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
