/** 
@author Graham Rosser <grosser@cs.brown.edu>
*/
#ifndef __GAME_UI_H

#define __GAME_UI_H



#include "dojo/dojo.h"

using namespace dojo;



/*

 * This is a simple system to add basic GUI elements to a system.

 * It allows for text objects, sprites, and buttons.

 * It's designed to be extremely lightweight, providing very basic 

 * functionality much like what you would need for a game like HalfLife:

 * sprites, simple mouseover buttons, and text items.  Very simple.

 */



typedef int UIHandle;



class GameUI

{

public:



    /* 

     * base class from which all UI widgets derive.  Subclass this.

     */

	class UIItem

	{

	public:

		UIItem(){}

		virtual ~UIItem(){}

		virtual void draw(RenderDevice *rd)=0;

		virtual void update(const Vector2 &mousepos, RealTime dt){}

		UIHandle handle;

		void setHandle(UIHandle h){handle = h;}

		virtual void setPos(const Vector2 &p){}

	};

	/*

	 * Button.  Represented by a rectangle and three textures 

	 * (neutral, mouse-hover, and down states)

	 */

	class UIButton : public UIItem

	{

	protected:

		TextureRef neutral, hover, down;

		Rect2D rect;

		bool pressed; //Is the button currently pressed?

		bool mouseover; //is the mouse over it?

	public:

		UIButton(const Rect2D &r, TextureRef n, TextureRef h, TextureRef d);

		virtual ~UIButton();

		void setPos(const Vector2 &p);

		void setRect(const Rect2D &r);

		//call whenever there is a mousedown/mouseup event

		bool reactClick(const Vector2 &click);

		virtual void draw(RenderDevice *rd);

		virtual void update(const Vector2 &mousepos, RealTime dt);

	};

	class UIText : public UIItem

	{

	protected:

		std::string toSay; //what to print to screen

		Vector2 pos; //where

		GFontRef font;

		double size;

		Color4 outlineColor;

		Color3 textColor;

		

	public:

		UIText(GFontRef f, double s, const Vector2 &p, std::string initialText, 

			const Color3 &color = Color3::black(),

			const Color4 &outline = Color4::clear());

		virtual ~UIText();

		void setPos(const Vector2 &p);

		void setText(const std::string &text);

		virtual void draw(RenderDevice *rd);

		GFont::XAlign xalign; //alignment options.  Default is

		GFont::YAlign yalign; //left, up

	};

	/*

	 * A sprite.  Can have an alpha channel.  Looks cool.

	 */

	class UISprite : public UIItem

	{

	protected:

		TextureRef image;

		Rect2D rect;

	public:

		UISprite(TextureRef i, const Rect2D &r);

		virtual ~UISprite();

		virtual void draw(RenderDevice *rd);

		void setRect(const Rect2D &r);

		void setPos(const Vector2 &p);

	};

	/*

	 * A simple version of sprites that fills the whole screen

	 */

	class UIBackground : public UISprite

	{

	public:

		UIBackground(TextureRef i);

		virtual ~UIBackground();

		virtual void draw(RenderDevice *rd);

	};



	/*

	 * tables to hold each type of item and

	 * an array to hold everything

	 */

	typedef Array<GameUI::UIItem*> UIArray;

	typedef Table<UIHandle,UIButton*> ButtonTable;

	typedef Table<UIHandle,UISprite*> SpriteTable;

	typedef Table<UIHandle,UIText*> TextTable;



protected:

	UIArray elements;

	ButtonTable buttons;

	TextTable texts;

	SpriteTable sprites;

	DApp *app;



public:

	GameUI(DApp *a);

	/*

	 * Can create a GameUI either hardcoded in C++

	 * or by using a scripted Lua file.

	 */

	GameUI(DApp *a, const std::string &luafile);

	void doLuaFile(const std::string &luafile);

	//pass in an array and get access to all the UIHandles, 

	//in the order in which they are created in the luafile

	void doLuaFile(const std::string &luafile, Array<UIHandle> &handles);

	virtual ~GameUI();



	/*

	 * functions to add an item with the given parameters

	 * to the system

	 */

	UIHandle addText(GFontRef font, double size, const Vector2 &pos, std::string initialText="",

		const Color3 &color = Color3::black(),

		const Color4 &outline = Color4::clear());

	UIHandle addButton(Rect2D pos, TextureRef neutral, TextureRef hover, TextureRef down);

	UIHandle addSprite(TextureRef image, const Rect2D &rect);

	UIHandle addBackground(TextureRef image);



	void doUIGraphics(RenderDevice *rd);

	/*

	 * Handles such things as mouseover events,

	 * and takes a RealTime in order to allow for animated sprites

	 * in future versions.

	 */

	void virtual update(const Vector2 &mousepos, RealTime dt);

	/*

	 * Call this whenever there is a mouseup/mousedown event that could

	 * trigger a button.

	 * Returns true if a button reacts, and sets the handle reference 

	 * to the given button.

	 */

	bool virtual doClick(const Vector2 &click, UIHandle &reactor);



	void setText(UIHandle h, const std::string &text);

	void setPos(UIHandle h, const Vector2 &pos);



	UIItem* getItem(UIHandle h);

};



#endif

