// ---------------------------------------------------------------------------
// 
//   Lily Engine alpha
// 
//   Copyright (c) 2010 Clifford Jolly
//     http://cliffjolly.com
//     cliff@cliffjolly.com
// 
// ---------------------------------------------------------------------------
// 
//   This program is free software; you can redistribute it and/or modify
//   it under the terms of the GNU General Public License as published by
//   the Free Software Foundation; either version 2 of the License, or
//   (at your option) any later version.
//  
//   This program is distributed in the hope that it will be useful, but
//   WITHOUT ANY WARRANTY; without even the implied warranty of
//   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
//   General Public License for more details.
// 
//   You should have received a copy of the GNU General Public License
//   along with this program; if not, write to the Free Software
//   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
//   USA
// -------------------------- END HEADER -------------------------------------

#include "../hacks/winhacks.h"

#include <limits>

#include "renderer.h"
#include "boundingbox.h"

BoundingBox::BoundingBox(void) : upperLeft(0, 0), lowerRight(0, 0) {
}

BoundingBox::BoundingBox(float left, float top, float right, float bottom) : upperLeft(left, top), lowerRight(right, bottom) {
}

BoundingBox::BoundingBox(const Vector2D &upperLeft, const Vector2D &lowerRight) : upperLeft(upperLeft), lowerRight(lowerRight) {
	
	// Okay, so it's really easy to screw up the totally non-intuitive
	// upper left / lower right thing, so I'm just going to
	// auto-correct it here and not deal with that crap from now on.
	
	float tmp;
	
	if(upperLeft.y < lowerRight.y) {
		tmp = upperLeft.y;
		this->upperLeft.y = lowerRight.y;
		this->lowerRight.y = tmp;
	}
	
	if(upperLeft.x > lowerRight.x) {
		tmp = upperLeft.x;
		this->upperLeft.x = lowerRight.x;
		this->lowerRight.x = tmp;
	}
	
}

BoundingBox::BoundingBox(const Polygon &poly) {
	assert(poly.points.size()); // We need a polygon with points to make something out of.
	
	// To make a bounding box from a Polygon, we just need to find the
	// maximum bounds of the points on it.
	upperLeft = poly.points[0];
	lowerRight = poly.points[0];
	for(unsigned int i = 1; i < poly.points.size(); i++) {
		if(poly.points[i].x < upperLeft.x) upperLeft.x = poly.points[i].x;
		if(poly.points[i].y > upperLeft.y) upperLeft.y = poly.points[i].y;
		if(poly.points[i].x > lowerRight.x) lowerRight.x = poly.points[i].x;
		if(poly.points[i].y < lowerRight.y) lowerRight.y = poly.points[i].y;
	}
	
	// Then add the polygon's offset.
	upperLeft += poly.offset;
	lowerRight += poly.offset;
}

BoundingBox BoundingBox::expand(const Vector2D &v) const {
	
	BoundingBox bb(*this);
	
	if(v.x < 0) {
		bb.upperLeft.x += v.x;
	} else {
		bb.lowerRight.x += v.x;
	}
	
	if(v.y > 0) {
		bb.upperLeft.y += v.y;
	} else {
		bb.lowerRight.y += v.y;
	}
	
	return bb;
}

BoundingBox BoundingBox::move(const Vector2D &v) const {
	return BoundingBox(upperLeft + v, lowerRight + v);
}

void BoundingBox::draw(Renderer *renderer) const {

	Vector2D points[] = {
		upperLeft,
		Vector2D(lowerRight.x, upperLeft.y),  // Upper right
		lowerRight,
		Vector2D(upperLeft.x, lowerRight.y), // Lower left
		upperLeft
	};
	
	renderer->drawLineStrip(points, 5);
}

bool BoundingBox::fits(const BoundingBox &otherBox) const {
	
	if(	otherBox.upperLeft.x  > upperLeft.x && otherBox.upperLeft.x  < lowerRight.x &&
		otherBox.lowerRight.x > upperLeft.x && otherBox.lowerRight.x < lowerRight.x &&
		otherBox.upperLeft.y  < upperLeft.y && otherBox.upperLeft.y  > lowerRight.y &&
		otherBox.lowerRight.y < upperLeft.y && otherBox.lowerRight.y > lowerRight.y) {
			
		return true;
	}
	
	return false;
}

Polygon BoundingBox::getPoly(void) const {
	Polygon poly;

	poly.points.push_back(upperLeft);
	poly.points.push_back(Vector2D(upperLeft.x, lowerRight.y));
	poly.points.push_back(lowerRight);
	poly.points.push_back(Vector2D(lowerRight.x, upperLeft.y));

	/*	
	poly.points.push_back(Vector2D(lowerRight.x, upperLeft.y));
	poly.points.push_back(lowerRight);
	poly.points.push_back(Vector2D(upperLeft.x, lowerRight.y));
	poly.points.push_back(upperLeft);
	*/
	
	return poly;
}
