#pragma once

#include <psemek/cg/body/body.hpp>
#include <psemek/math/simplex.hpp>

#include <vector>
#include <cstdint>

namespace psemek::cg
{
	template <typename T, typename Index = std::uint32_t>
	struct triangle_mesh
	{
		triangle_mesh() = default;
		triangle_mesh(std::vector<math::point<T, 3>> vertices, std::vector<math::triangle<Index>> triangles);

		std::vector<math::point<T, 3>> vertices;
		std::vector<math::triangle<Index>> triangles;
		std::vector<math::segment<Index>> edges;
		std::vector<math::vector<T, 3>> edge_directions;
	};

	template <typename T, typename Index>
	triangle_mesh<T, Index>::triangle_mesh(std::vector<math::point<T, 3>> vertices, std::vector<math::triangle<Index>> triangles)
		: vertices(std::move(vertices))
		, triangles(std::move(triangles))
	{
		for (auto const & t : this->triangles)
		{
			// Add each edge just once
			if (t[0] < t[1]) edges.push_back({t[0], t[1]});
			if (t[1] < t[2]) edges.push_back({t[1], t[2]});
			if (t[2] < t[0]) edges.push_back({t[2], t[0]});
		}

		for (auto const & e : edges)
			edge_directions.push_back(math::normalized(this->vertices[e[1]] - this->vertices[e[0]]));
	}

	template <typename T, typename Index>
	auto const & vertices(triangle_mesh<T, Index> const & m)
	{
		return m.vertices;
	}

	template <typename T, typename Index>
	auto const & edges(triangle_mesh<T, Index> const & m)
	{
		return m.edges;
	}

	template <typename T, typename Index>
	auto const & edge_directions(triangle_mesh<T, Index> const & m)
	{
		return m.edge_directions;
	}

	template <typename T, typename Index>
	auto const & triangles(triangle_mesh<T, Index> const & m)
	{
		return m.triangles;
	}

}
