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


#ifndef	__NUIITEM__
#define	__NUIITEM__


		#include "automation/automation_player.h"
		#include "ui/ui_item_event_interface.h"
		#include "script/scripted_object.h"
		#include "math/matrix3.h"
		#include "geometry/rect.h"
		#include "container/nlist.h"
		#include "nstring/nstring.h"
		#include "memory/nshared_ptr.h"
		#include "memory/bit_field.h"
		#include "memory/nauto_ptr.h"


namespace GS {
	namespace GPU { class TriangleBatch; }
	namespace Core { struct ResourceFactories; }
	namespace Render { class Renderer; }

	namespace S2D {
		class EventTable;

		using Render::Renderer;

/*!
	@short	UI Item.
	@author	Emmanuel Julien (ejulien@nworks.fr)
*/
class	Item : public SharedObject
{
		friend class Scene;

public:

enum	Type
{
		Type_None			=	0,
		Type_Camera,
		Type_Sprite,
		Type_Window
};

enum	Flag
{
		Flag_ItemActive		=	(1 << 0)
};

protected:

		uint			uid;
		Type			type;

		Item			*parent;

		Vector2			position, pivot, size, scale;
		float			zorder, angle;

		Matrix3			local_matrix, matrix, imatrix;

		List <Item *>	children;	///< Children list.

public:

		String			name;

		BitField		item_flags;

		uint			GetUid() const { return uid; }
		Type			GetItemType() const	{ return type; }

virtual	EventTable		*GetEventTable() const { return 0; }

		Item			*GetParent() const { return parent; }
		void			SetParent(Item * = 0);

		bool			Inherits(const Item *) const;

		List <Item *>	&GetChildren() { return children; }

		void			ComputeMatrix();

		const Matrix3	&GetLocalMatrix() { return local_matrix; }
		const Matrix3	&GetMatrix() { return matrix; }
		const Matrix3	&GetInverseMatrix() { return imatrix; }

		/// Snapshot a transformation to this sprite position, rotation and scale.
		void			SnapshotTransformation(const Matrix3 &);

		float			GetZOrder() const { return zorder; }
		void			SetZOrder(float z) { zorder = z; }
		Vector2			GetPosition() const { return position; }
		void			SetPosition(float x, float y) { position.Set(x, y); }
		Vector2			GetPivot() const { return pivot; }
		void			SetPivot(float x, float y) { pivot.Set(x, y); }
		Vector2			GetScale() const { return scale; }
		void			SetScale(float x, float y) { scale.Set(x, y); }
		Vector2			GetSize() const { return size; }
virtual	void			SetSize(float x, float y) { size.Set(Types::Max <float> (1, x), Types::Max <float> (1, y)); }

		float			GetRotation() const { return angle; }
		void			SetRotation(float a) { angle = a; }

		/// Rectangle in local space.
virtual	iRect			GetRect() const;
		/// Rectangle in screen space.
virtual	iRect			GetScreenRect() const;

		iRect			LocalToScreen(const iRect &) const;
		iRect			ScreenToLocal(const iRect &) const;
		Vector2			LocalToScreen(const Vector2 &) const;
		Vector2			ScreenToLocal(const Vector2 &) const;

virtual	void			RenderSetup(Core::ResourceFactories * = 0) = 0;
virtual	void			Render(Renderer &, GPU::TriangleBatch * = 0) = 0;

		AutoPtr <IItemEvent> item_event;
		AutoPtr <Script::ScriptedObject> scripted_object;
		AutoPtr <GS::Automation::Player> automation_player;

		void			Reset();
		void			Setup();

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

		Item();
virtual	~Item();
};

	} // S2D
} // GS


#endif	// __NUIITEM__
