/***************************************************************************
*                                                                          *
*  Copyright (C) Golaem S.A.  All Rights Reserved.                         *
*                                                                          *
***************************************************************************/

#pragma once

#include "glmVector2.h"
#include "glmPODArray.h"
#include "glmArray.h"

namespace glm
{
	/**
	* \brief A 2 dimension counterclockwise ordered (positive) convex polygon.
	* 
	* \ingroup geometry2
	* \author Golaem <dev@golaem.com>
	*
	* \param float Manipulated scalar type (\ref double, float...)
	*/

	class GLM_CORE_API ConvexPolygon2
	{
	public:
		struct GlmPolygonStatus
		{
			enum Value
			{
				INVALID, //!< The convex polygon is invalid (ie has less than 3 vertices or is not convex)
				UNKNOWN, //!< The status of the polygon is unknown (ie it has not been computed yet)
				CW,      //!< The polygon is valid, its vertices are clockwise ordered
				CCW,     //!< The polygon is valid, its vertices are counter-clockwiser ordered
				END
			};
		};
	public:

		GLM_CLASS_STAT_ID( glm::MemoryStatIds::GolaemShared)

		/**
		* \name Construction/Destruction
		*/
		//@{
		/**
		* \brief Default constructor.
		*/
		ConvexPolygon2();

		/**
		* \brief Constructor.
		* \param vertices The vertices, to be copied in the polygon.
		* \param status The status of the polygon (default is GlmPolygonStatus::UNKNOWN).
		*/
		ConvexPolygon2(const glm::Array< Vector2 >& vertices, GlmPolygonStatus::Value status = GlmPolygonStatus::UNKNOWN);

		/**
		* \brief Copy constructor.
		*/
		ConvexPolygon2(const ConvexPolygon2& polygon);

		/**
		* \brief Assigment operator
		*/
		ConvexPolygon2& operator=(const ConvexPolygon2& polygon);
		//@}

		/**
		* \name Vertices
		*/
		//@{
		const Vector2& operator[](unsigned int index) const; 

		const Vector2& getVertex(unsigned int index) const; 

		unsigned int countVertices() const;

		/**
		* \brief Set the vertices of the convex polygon.
		* \param vertices The vertices, to be copied in the polygon.
		* \param status The new status of the polygon (default is GlmPolygonStatus::UNKNOWN).
		*/
		void setVertices(const glm::Array< Vector2 >& vertices, GlmPolygonStatus::Value status = GlmPolygonStatus::UNKNOWN);

		const glm::Array< Vector2 >& getVertices() const;

		/**
		* \brief Touch the polygon vertices.
		* \warning This method sets the status of the polygon to GlmPolygonStatus::UNKNOWN.
		*/
		glm::Array< Vector2 >& touchVertices();
		//@}

		/**
		* \brief Retrieve the status of the polygon.
		* \see ConvexPolygon2::GlmPolygonStatus
		* \param forceComputation If true the status is recomputed (default is false).
		* \param computeIfUnknown If true the status is computed if it is unknown (default is true).
		* \return The status of the convex polygon.
		*/
		GlmPolygonStatus::Value getStatus(bool forceComputation = false, bool computeIfUnknown = true) const;

		/**
		* \brief Set the instance to the convex hull of the given positions.
		*/
		ConvexPolygon2& computeConvexHull(glm::Array< Vector2 > positions);

		/**
		* \name Comparisons
		*/
		//@{
		bool operator==(const ConvexPolygon2& polygon) const;
		bool operator!=(const ConvexPolygon2& polygon) const;
		//@}
	private:

		/// The vertices of the polygon.
		glm::Array< Vector2 > _vertices;

		/// The convex polygon status 
		mutable int _status;
	};
}

