/* -----------------------------------------------------------------------------
	GSFramework
	Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
----------------------------------------------------------------------------- */


#ifndef	__NRECT__
#define	__NRECT__


		#include "ntypes.h"


namespace GS {
	namespace NML {
		class File;
		class Tag;
	}

/*!
	@short	Point.
	@author	Emmanuel Julien (ejulien@nworks.fr)
*/
template <class T> struct Point
{
		T			x, y;

		T			operator [] (size_t n) const { return *(&x + n); }

		void		Set(T _x, T _y)
		{	x = _x; y = _y;	}

		Point(T ux, T uy) : x(ux), y(uy) {}
		Point() : x(0), y(0) {}
};

typedef	Point <int> iPoint;
typedef	Point <float> fPoint;

/*!
	@short	Rectangle.
	@author	Emmanuel Julien (ejulien@nworks.fr)
*/
template <class T> struct Rect
{
		T			sx, sy, ex, ey;

		void		SetWidth(T w) { ex = sx + w; }
		void		SetHeight(T h) { ey = sy + h; }
		T			GetWidth() const { return ex - sx; }
		T			GetHeight()	const { return ey - sy; }

		Rect <T>	operator * (T v) const
		{	return Rect <T> (sx * v, sy * v, ex * v, ey * v);	}
		Rect <T>	operator / (T v) const
		{	return Rect <T> (sx / v, sy / v, ex / v, ey / v);	}

		bool		Inside(T x, T y) const
		{	return (x > sx) && (y > sy) && (x < ex) && (y < ey);	}

		bool		FitsInside(const Rect <T> &b) const
		{	return (GetWidth() <= b.GetWidth()) && (GetHeight() <= b.GetHeight());	}

		bool		Intersect(const Rect <T> &b) const
		{	return ((ex < b.sx) || (ey < b.sy) || (sx > b.ex) || (sy > b.ey)) ? false : true;	}

		Rect <T>	Intersection(const Rect <T> &b) const
		{
			T	_sx = Types::Max(sx, b.sx), _sy = Types::Max(sy, b.sy),
				_ex = Types::Min(ex, b.ex), _ey = Types::Min(ey, b.ey);

			T	n_sx = Types::Min(_sx, _ex), n_sy = Types::Min(_sy, _ey),
				n_ex = Types::Max(_sx, _ex), n_ey = Types::Max(_sy, _ey);

			return Rect <T> (_sx = n_sx, _sy = n_sy, _ex = n_ex, _ey = n_ey);
		}

		Rect <T>	Grow(T border) const
		{	return Rect <T> (sx - border, sy - border, ex + border, ey + border);	}

		void		Set(T usx, T usy, T uex, T uey)
		{	sx = usx; sy = usy; ex = uex; ey = uey;		}
		void		Set(T ux = 0, T uy = 0)
		{	sx = ux; sy = uy; ex = ux; ey = uy;		}

		Rect <T>	Offset(T x, T y) const
		{	return Rect <T> (sx + x, sy + y, ex + x, ey + y);	}

		Rect <float> AsFloat() const
		{	return Rect <float> (float(sx), float(sy), float(ex), float(ey));	}
		Rect <int>	AsInt() const
		{	return Rect <int> (int(sx), int(sy), int(ex), int(ey));	}

		NML::Tag	*AsMetaTag(const char *id) const;
		bool		FromMetaTag(NML::Tag &);

static	Rect <T>	FromWidthHeight(T sx, T sy, T w, T h)
		{	return Rect <T> (sx, sy, sx + w, sy + h);	}

		Rect(const Rect <T> &b) : sx(b.sx), sy(b.sy), ex(b.ex), ey(b.ey) {}
		Rect(T usx, T usy, T uex, T uey) : sx(usx), sy(usy), ex(uex), ey(uey) {}
		Rect(T usx, T usy) : sx(usx), ex(usx), sy(usy), ey(usy) {}
		Rect() : sx(0), sy(0), ex(0), ey(0) {}
};

typedef	Rect <int> iRect;
typedef	Rect <float> fRect;

} // GS


#endif	// __NRECT__
