#ifndef INCLUDED_MATH_POINT
#define INCLUDED_MATH_POINT

#include <sstream>

//////////////////////////////////////////////////////////////
namespace Dubious {
namespace Math {

/// @brief A 2D Point
///
///	Template class to represent a 2D Point.  It's templated so that
///	I can create different classes for global points, local points, and
///	sizes.  
template <int T>
class PointTemplate
{
public:
	/// @brief Constructor.  Creates a point a (0,0)
	PointTemplate()
		: m_X(0), m_Y(0)
	{
	}

	/// @brief Constructor.  Creates a point a (X,Y)
	/// @param X - [in] X coord
	/// @param Y - [in] Y coord
	PointTemplate( int X, int Y )
		: m_X(X), m_Y(Y)
	{
	}

	/// @brief Destructor
	~PointTemplate()
	{
	}

	/// @brief X Accessor
	/// @returns X coord
	const int			X() const { return m_X; }

	/// @brief Y Accessor
	/// @returns Y coord
	const int			Y() const { return m_Y; }

private:
	int					m_X;
	int					m_Y;
};

typedef PointTemplate<0> Point;
typedef PointTemplate<1> LocalPoint;
typedef PointTemplate<2> Size;

//////////////////////////////////////////////////////////////
template<int T> 
inline bool operator==( const PointTemplate<T>& A, const PointTemplate<T>& B )
{
	return A.X() == B.X() && A.Y() == B.Y();
}

//////////////////////////////////////////////////////////////
template<int T> 
inline PointTemplate<T> operator+( const PointTemplate<T>& A, const PointTemplate<T>& B )
{
	return PointTemplate<T>( A.X()+B.X(), A.Y()+B.Y() );
}

//////////////////////////////////////////////////////////////
template<int T> 
inline PointTemplate<T> operator-( const PointTemplate<T>& A, const PointTemplate<T>& B )
{
	return PointTemplate<T>( A.X()-B.X(), A.Y()-B.Y() );
}

//////////////////////////////////////////////////////////////
template<int T>
inline PointTemplate<T> operator*( const PointTemplate<T>& A, float B )
{
	return PointTemplate<T>( A.X()*B, A.Y()*B );
}

//////////////////////////////////////////////////////////////
template<int T>
inline PointTemplate<T> operator/( const PointTemplate<T>& A, float B )
{
	return PointTemplate<T>( A.X()/B, A.Y()/B );
}

//////////////////////////////////////////////////////////////
template<int T>
inline std::ostream& operator<<( std::ostream& o, const PointTemplate<T>& P )
{
	o << "(" << P.X() << ", " << P.Y() << ")";
	return o;
}

}
}

#endif
