/*
 * 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 "include/core/SkPath.h"
#include "include/core/SkPathBuilder.h"
#include "include/core/SkPoint.h"
#include "include/private/SkAssert.h"
#include "include/private/SkTo.h"
#include "modules/jsonreader/SkJSONReader.h"
#include "modules/skottie/src/SkottieJson.h"
#include "modules/skottie/src/SkottieValue.h"
#include "modules/skottie/src/animator/Animator.h"
#include "modules/skottie/src/animator/VectorKeyframeAnimator.h"

#include <cstddef>
#include <vector>

namespace skottie::internal {
class AnimationBuilder;
}

namespace skottie {

// Shapes (paths) are encoded as a vector of floats.  For each vertex, we store 6 floats:
//
//   - vertex point      (2 floats)
//   - in-tangent point  (2 floats)
//   - out-tangent point (2 floats)
//
// Additionally, we store one trailing "closed shape" flag - e.g.
//
//  [ v0.x, v0.y, v0_in.x, v0_in.y, v0_out.x, v0_out.y, ... , closed_flag ]
//
enum ShapeEncodingInfo : size_t {
            kX_Index = 0,
            kY_Index = 1,
          kInX_Index = 2,
          kInY_Index = 3,
         kOutX_Index = 4,
         kOutY_Index = 5,

    kFloatsPerVertex = 6
};

static size_t shape_encoding_len(size_t vertex_count) {
    return vertex_count * kFloatsPerVertex + 1;
}

// Some versions wrap shape values as single-element arrays.
static const skjson::ObjectValue* shape_root(const skjson::Value& jv) {
    if (const skjson::ArrayValue* av = jv) {
        if (av->size() == 1) {
            return (*av)[0];
        }
    }

    return jv;
}

static bool parse_encoding_len(const skjson::Value& jv, size_t* len) {
    if (const auto* jshape = shape_root(jv)) {
        if (const skjson::ArrayValue* jvs = (*jshape)["v"]) {
            *len = shape_encoding_len(jvs->size());
            return true;
        }
    }
    return false;
}

static bool parse_encoding_data(const skjson::Value& jv, size_t data_len, float data[]) {
    const auto* jshape = shape_root(jv);
    if (!jshape) {
        return false;
    }

    // vertices are required, in/out tangents are optional
    const skjson::ArrayValue* jvs = (*jshape)["v"]; // vertex points
    const skjson::ArrayValue* jis = (*jshape)["i"]; // in-tangent points
    const skjson::ArrayValue* jos = (*jshape)["o"]; // out-tangent points

    if (!jvs || data_len != shape_encoding_len(jvs->size())) {
        return false;
    }

    auto parse_point = [](const skjson::ArrayValue* ja, size_t i, float* x, float* y) {
        SkASSERT(ja);
        const skjson::ArrayValue* jpt = (*ja)[i];

        if (!jpt || jpt->size() != 2ul) {
            return false;
        }

        return Parse((*jpt)[0], x) && Parse((*jpt)[1], y);
    };

    auto parse_optional_point = [&parse_point](const skjson::ArrayValue* ja, size_t i,
                                               float* x, float* y) {
        if (!ja || i >= ja->size()) {
            // default control point
            *x = *y = 0;
            return true;
        }

        return parse_point(*ja, i, x, y);
    };

    for (size_t i = 0; i < jvs->size(); ++i) {
        float* dst = data + i * kFloatsPerVertex;
        SkASSERT(dst + kFloatsPerVertex <= data + data_len);

        if (!parse_point         (jvs, i, dst +    kX_Index, dst +    kY_Index) ||
            !parse_optional_point(jis, i, dst +  kInX_Index, dst +  kInY_Index) ||
            !parse_optional_point(jos, i, dst + kOutX_Index, dst + kOutY_Index)) {
            return false;
        }
    }

    // "closed" flag
    data[data_len - 1] = ParseDefault<bool>((*jshape)["c"], false);

    return true;
}

ShapeValue::operator SkPath() const {
    const auto vertex_count = this->size() / kFloatsPerVertex;

    SkPathBuilder path;

    if (vertex_count) {
        // conservatively assume all cubics
        path.incReserve(1 + SkToInt(vertex_count * 3));

        // Move to first vertex.
        path.moveTo((*this)[kX_Index], (*this)[kY_Index]);
    }

    auto addCubic = [&](size_t from_vertex, size_t to_vertex) {
        const auto from_index = kFloatsPerVertex * from_vertex,
                     to_index = kFloatsPerVertex *   to_vertex;

        const SkPoint p0 = SkPoint{ (*this)[from_index +    kX_Index],
                                    (*this)[from_index +    kY_Index] },
                      p1 = SkPoint{ (*this)[  to_index +    kX_Index],
                                    (*this)[  to_index +    kY_Index] },
                      c0 = SkPoint{ (*this)[from_index + kOutX_Index],
                                    (*this)[from_index + kOutY_Index] } + p0,
                      c1 = SkPoint{ (*this)[  to_index +  kInX_Index],
                                    (*this)[  to_index +  kInY_Index] } + p1;

        if (c0 == p0 && c1 == p1) {
            // If the control points are coincident, we can power-reduce to a straight line.
            // TODO: we could also do that when the controls are on the same line as the
            //       vertices, but it's unclear how common that case is.
            path.lineTo(p1);
        } else {
            path.cubicTo(c0, c1, p1);
        }
    };

    for (size_t i = 1; i < vertex_count; ++i) {
        addCubic(i - 1, i);
    }

    // Close the path with an extra cubic, if needed.
    if (vertex_count && this->back() != 0) {
        addCubic(vertex_count - 1, 0);
        path.close();
    }

    return path.detach();
}

namespace internal {

template <>
bool AnimatablePropertyContainer::bind<ShapeValue>(const AnimationBuilder& abuilder,
                                                  const skjson::ObjectValue* jprop,
                                                  ShapeValue* v) {
    VectorAnimatorBuilder builder(v, parse_encoding_len, parse_encoding_data);

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

} // namespace internal

} // namespace skottie
