#include "triangulization.hpp"
#include "earcut.hpp"
#include "godot_cpp/core/class_db.hpp"
#include "godot_cpp/variant/array.hpp"
#include "godot_cpp/variant/packed_int32_array.hpp"
#include "godot_cpp/variant/packed_vector2_array.hpp"
#include "godot_cpp/variant/string.hpp"
#include "godot_cpp/variant/typed_array.hpp"
#include "godot_cpp/variant/vector2.hpp"
#include <cstdint>
#include <vector>

Triangulization::Triangulization() {}

void Triangulization::_bind_methods() {
  ClassDB::bind_method(
      godot::D_METHOD("triangulate_with_holes", "outer", "inner"),
      &Triangulization::triangulate_with_holes);
}

std::vector<Vector2>
_convert_to_std_vec2(const godot::PackedVector2Array &packed_array) {
  std::vector<Vector2> std_vec;
  std_vec.reserve(packed_array.size());

  for (int i = 0; i < packed_array.size(); i++) {
    std_vec.push_back(packed_array.get(i));
  }

  return std_vec;
}

PackedInt32Array Triangulization::triangulate_with_holes(
    const PackedVector2Array &outer,
    const TypedArray<PackedVector2Array> &inner) {
  std::vector<std::vector<Vector2>> p;

  p.push_back(_convert_to_std_vec2(outer));

  for (int i = 0; i < inner.size(); i++) {
    p.push_back(_convert_to_std_vec2(inner[i]));
  }

  std::vector<uint32_t> indices = mapbox::earcut<uint32_t>(p);

  PackedInt32Array return_values;
  for (int i = indices.size() - 1; i >= 0; i--) {
    return_values.push_back(indices[i]);
  }

  return return_values;
};
