#include <iostream>
#include "Box.hpp"

namespace nbody {
	using namespace std;

	Box::Box() {
	}

	Box::~Box() {
	}

	//min/max getter/setters
	double Box::getMin(int index) {
		return this->min[index];
	}

	double Box::getMax(int index) {
		return this->max[index];
	}

	void Box::setMin(int index, double value) {
		this->min[index] = value;
	}

	void Box::setMax(int index, double value) {
		this->max[index] = value;
	}

	void Box::extendToCube() {
		int longestSide = -1;
		double sidelength = 0.0;

		for (int i = 0; i < 3; i++) {
			if (this->max[i] - this->min[i] >= sidelength) {
				longestSide = i;
				sidelength = this->max[i] - this->min[i];
			}
		}
		if (longestSide == -1) {
			return;
		}
		for (int i = 0; i < 3; i++) {
			if (i != longestSide) {
				double extend = (sidelength - (this->max[i] - this->min[i])) / 2.0;

				this->min[i] -= extend;
				this->max[i] += extend;
			}
		}
	}

	vector<Body> Box::containedBodies(vector<Body> bodies) {
		vector<Body> result;

		for (vector<Body>::iterator it = bodies.begin(); it != bodies.end(); it++) {
			if (it->getPosition(0) >= this->min[0] && it->getPosition(0) <= this->max[0] &&
					it->getPosition(1) >= this->min[1] && it->getPosition(1) <= this->max[1] &&
					it->getPosition(2) >= this->min[2] && it->getPosition(2) <= this->max[2]) {
				result.push_back(*it);
			}
		}
		return result;
	}

	bool Box::isContained(Body body) {
		for (int i = 0; i < 3; i++) {
			if (body.getPosition(i) < this->min[i] || body.getPosition(i) > this->max[i]) {
				return false;
			}
		}
		return true;
	}

	//TODO: check semantics
	bool Box::isContained(Box box) {
		for (int i = 0; i < 3; i++) {
			if (box.min[i] < this->min[i] || box.max[i] > this->max[i]) {
				return false;
			}
		}
		return true;
	}

	double Box::volume() {
		double result = 1.0;

		for (int i = 0; i < 3; i++) {
			result *= this->max[i] - this->min[i];
		}
		return result;
	}

	bool Box::isCorrect() {
		for (int i = 0; i < 3; i++) {
			if (this->max[i] < this->min[i]) {
				cout << "inverted bb" << endl;
				return false;
			}
		}
		return true;
	}

	void Box::print() {
		for (int i = 0; i < 3; i++) {
			cout << i << " min " << this->min[i] << " max " << this->max[i] << endl;
		}
	}
}
