// ---------------------------------------------------------------------------
// 
//   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 -------------------------------------

#pragma once

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

#include <vector>

#include "../math/vector2d.h"

#ifdef WIN32
// Okay, this is REALLY retarded.
#define Polygon PolygonShape
#endif

class Renderer;

/** @brief A convex polygon representation. */
class Polygon {
	public:
		/// All the points in the polygon.
		std::vector<Vector2D> points;
		
		/// For displaying and calculations, this is added to all point values.
		Vector2D offset;
		
		/** @brief Draw the polygon as a wireframe.
		 * */
		void draw(Renderer *renderer) const;
		
		/** @brief Draw the polygon as a solid.
		 * */
		void drawSolid(Renderer *renderer) const;
		
		/** @brief Get a swept polygon.
		 * @param sweep The direction and distance to extrude in.
		 * @note There's some weirdness with this - the points must be
		 *   in counter-clockwise order in order for this to function
		 *   properly. (FIXME)
		 * @return A Polygon, that is this one extruded by sweep.
		 * */
		Polygon getSweep(const Vector2D &sweep) const;
		
		/** @brief Detect and force convexity of the polygon, changing
		 * the given point if needed.
		 * @param index The index of the point that will change if it's
		 *   needed to enforce convexity.
		 * */
		void fixConcave(int index);
		
		/** @brief Get the cross product of the vectors from the point
		 * at the given index to its neighboring points.
		 * @note This doesn't change anything, but calls non-const
		 *   member functions.
		 * @param index The index of the point.
		 * @return The Z part of the cross product.
		 * */
		float getPointCross(int index); 
		
		/** @brief Get a pointer to the actual Vector2D for the given
		 * index.
		 * @param index The index of the point to get. Will wrap
		 *   around if greater than the index of the last point or less
		 *   than zero.
		 * @return A pointer to the Vector2D to allow direct
		 *   modification of the point.
		 * */
		Vector2D *getPoint(int index);
};

// NOTE: Polygons need counter-clockwise order. Otherwise they screw up.
//   (Only on the sweep function, though - so if you don't use that do whatever.)

/** @brief Do a separating axis test to see if one polygon overlaps
 * another.
 * @note To get a complete overlap test, this function must be called
 *   twice - with p1 and p2 swapped also.
 * @note Don't use bounceAxis.
 * @param p1 The first Polygon.
 * @param p2 The second Polygon.
 * @param shortestOverlap Pointer to a Vector2D to fill with the
 *   shortest overlap between the two polygons (so they may be moved
 *   back apart).
 * @param bounceAxis Extra axis for calculating bounces. FIXME: Don't
 *   use this, it's broken.
 * @return true if there is an overlap.
 * */
bool separatingAxisTest(const Polygon &p1, const Polygon &p2, Vector2D *shortestOverlap = NULL, Vector2D *bounceAxis = NULL);
