#ifndef BOX_HPP
#define BOX_HPP

#include <array>
#include <limits>
#include <vector>

#include "Body.hpp"
#include "Vec3.hpp"

namespace nbody {
	struct Box {
		using flt_lim = std::numeric_limits<float>;
		Box() = default;
		Box(const Vec3& min_, const Vec3& max_) : min(min_), max(max_) {};
		Box(const std::vector<Body>& bodies) { extendForBodies(bodies); }
		Vec3 min{ flt_lim::max() };
		Vec3 max{ flt_lim::min() };

		void extendToCube();
		void extendForBodies(const std::vector<Body>& bodies);
		std::vector<Body> extractBodies(std::vector<Body>& bodies) const;
		std::vector<Body> copyBodies(const std::vector<Body>& bodies) const;
		double volume() const;
		double maxSidelength() const;
		bool isCorrectBox() const;
		bool isValid() const;
		void printBB(std::size_t parallelId) const;
		double distanceToPosition(const Vec3& position) const;
		double distanceToBox(const Box& box2) const;
		std::array<Box, 8> octreeSplit() const;
		std::array<Box, 2> splitLongestSide() const;
		bool contained(const Vec3& position) const;
		void extend(const Body& extender);
	};
	Box extend(const Box& first, const Box& second);
	bool isContained(const Body& body, const Box& box);
	bool isContained(const Box& inner, const Box& outer);

} // namespace nbody

#endif
