#pragma once

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

#include <cstdint>

namespace psemek::cg
{

	template <typename T>
	struct icosahedron
	{
		icosahedron() = default;
		icosahedron(math::point<T, 3> const & origin, T radius);

		std::array<math::point<T, 3>, 12> vertices;
	};

	template <typename T>
	icosahedron<T>::icosahedron(math::point<T, 3> const & origin, T radius)
	{
		static const T icosa_a = radius * 0.850650808; // radius * phi / sqrt(1 + phi^2)
		static const T icosa_b = radius * 0.525731112; // radius / sqrt(1 + phi^2)

		vertices =
		{{
			origin + math::vector<T, 3>{-icosa_a, -icosa_b, 0}, //  0
			origin + math::vector<T, 3>{-icosa_a,  icosa_b, 0}, //  1
			origin + math::vector<T, 3>{ icosa_a, -icosa_b, 0}, //  2
			origin + math::vector<T, 3>{ icosa_a,  icosa_b, 0}, //  3

			origin + math::vector<T, 3>{0, -icosa_a, -icosa_b}, //  4
			origin + math::vector<T, 3>{0, -icosa_a,  icosa_b}, //  5
			origin + math::vector<T, 3>{0,  icosa_a, -icosa_b}, //  6
			origin + math::vector<T, 3>{0,  icosa_a,  icosa_b}, //  7

			origin + math::vector<T, 3>{-icosa_b, 0, -icosa_a}, //  8
			origin + math::vector<T, 3>{ icosa_b, 0, -icosa_a}, //  9
			origin + math::vector<T, 3>{-icosa_b, 0,  icosa_a}, // 10
			origin + math::vector<T, 3>{ icosa_b, 0,  icosa_a}, // 11
		}};
	}

	template <typename T>
	auto const & vertices(icosahedron<T> const & i)
	{
		return i.vertices;
	}

	template <typename T>
	auto const & triangles(icosahedron<T> const &)
	{
		static const std::array<math::triangle<std::uint8_t>, 20> result =
		{{
			{0, 1, 8,},
			{0, 10, 1,},
			{2, 9, 3,},
			{2, 3, 11,},
			{4, 5, 0,},
			{4, 2, 5,},
			{6, 1, 7,},
			{6, 7, 3,},
			{8, 9, 4,},
			{8, 6, 9,},
			{10, 5, 11,},
			{10, 11, 7,},
			{0, 8, 4,},
			{0, 5, 10,},
			{1, 6, 8,},
			{1, 10, 7,},
			{2, 4, 9,},
			{2, 11, 5,},
			{3, 9, 6,},
			{3, 7, 11},
		}};

		return result;
	}

}
