#ifndef BOX_HPP
#define BOX_HPP

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

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

namespace nbody {
	struct Box {
		Vec3 min{ std::numeric_limits<double>::max() };
		Vec3 max{ std::numeric_limits<double>::min() };

		Box() = default;
		Box(Vec3 min_, Vec3 max_) : min(min_), max(max_) {}
		explicit Box(const std::vector<Body>& bodies) { extendForBodies(bodies); }

		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 distanceSquaredToBox(Box box2) const;
		std::array<Box, 8> octreeSplit() const;
		std::array<Box, 2> splitLongestSide() const;
		bool contained(Vec3 position) const;
		void extend(const Body& extender);

		struct LongestSide {
			std::size_t Idx;
			double Length;
		};
		LongestSide longestSide() const;

	};
	Box extend(Box first, Box second);
	bool isContained(const Body& body, Box box);
	bool isContained(Box inner, Box outer);

} // namespace nbody

#endif
