/*
 * 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 "include/core/SkPathBuilder.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"

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
