//
// File: Control.h
// Created by: Alexander Oster - tensor@ultima-iris.de
//
/*****
*
*  This program is free software; you can redistribute it and/or modify
*  it under the terms of the GNU General Public License as published by
*  the Free Software Foundation; either version 2 of the License, or
*  (at your option) any later version.
*
*  This program is distributed in the hope that it will be useful,
*  but WITHOUT ANY WARRANTY; without even the implied warranty of
*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
*  GNU General Public License for more details.
*
*  You should have received a copy of the GNU General Public License
*  along with this program; if not, write to the Free Software
*  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*
*****/

#ifndef _CONTROL_H_
#define _CONTROL_H_

#ifdef WIN32
#include <windows.h>
#endif

#include "SDL/SDL.h"
#include "../renderer/Texture.h"
#include "../Config.h"
#include "rect.h"
#include "Stack.h"
#include "Gump.h"
#include <map>
#include <list>

namespace GUI {

enum GUMPFLAG {
	GUMPFLAG_MOVABLE   = 1,
	GUMPFLAG_CLOSABLE  = 2,
	GUMPFLAG_FOCUSABLE = 4,
	GUMPFLAG_ALPHA     = 8
};

enum SCRIPT_FUNC {
	FUNC_ONCLICK = 0,
	FUNC_ONCLOSE,
	FUNC_ONMOUSEUP,
	FUNC_ONMOUSEDOWN,
	FUNC_ONKEYPRESSED,
	FUNC_ONCHANGE,
	FUNC_ONDRAGDROP,
	FUNC_ONTIMER,
	SCRIPT_FUNC_COUNT = 10
};

enum CONTROLTYPE {
	CONTROLTYPE_UNKNOWN = 0,
	CONTROLTYPE_BORDER,
	CONTROLTYPE_CHECKBOX,
	CONTROLTYPE_CONTAINER,
	CONTROLTYPE_IMAGE,
	CONTROLTYPE_INPUTFIELD,
	CONTROLTYPE_LABEL,
	CONTROLTYPE_RADIOBUTTON,
	CONTROLTYPE_TEXTBOX,
	CONTROLTYPE_BUTTON,
	CONTROLTYPE_IMAGEART,
	CONTROLTYPE_ITEMCONTAINER,
	CONTROLTYPE_PAPERDOLL,
	CONTROLTYPE_MULTILABEL,
	CONTROLTYPE_SCROLLBAR
};

class Control;
class Container;

typedef std::map<Uint32, Control *>	ControlList_t;

class Control
{
public:
	Control ();
	virtual ~Control ();
	void SetPosition(int x, int y);
	void SetSize(int width, int height);
	void SetX (int x);
	void SetY (int y);
	void SetZ (int z);
	void SetFlags (int flags);
	void SetFlag (int flag, int value);
	void SetID (int id);
	void SetFocus (int focus);
	virtual void SetAlpha (unsigned char alpha);
	void SetTag(void * tag);
	void SetData(int slot, int tag);

	void SetParent(Control *);
	Control * GetParent(void);

	void GetPosition(int * x, int * y);
	int GetX(void);
	int GetY(void);
	int GetZ(void);
	int GetID(void);
	int GetFocus(void);
	int GetWidth(void);
	int GetHeight(void);
	int GetFlags(void);
	int GetFlag(int flag);

	void * GetTag(void);
	unsigned char GetAlpha(void);
	int GetData(int slot);

	virtual bool MouseIsOver( int x, int y);

	virtual int HandleMessage(gui_message * msg);
	virtual void Draw(GumpHandler * gumps);

	void DrawRectHued(int x, int y, int width, int height, Texture * texture, int hue, unsigned char alpha, bool swapy = false );
	void DrawRect(int x, int y, int width, int height, Texture * texture, unsigned char alpha, bool swapy = false );
	void DrawRect(int x, int y, int width, int height, Texture * texture, int alpha = 255);
	void DrawRect(int x, int y, Texture * texture, int alpha = 255);
	Texture * LoadGump(int id, GumpHandler * gumps, bool tileable);
	Texture * LoadGumpTiled(int id, GumpHandler * gumps, int width, int height);
	Texture * GetTiledGump( unsigned short id, short width, short height );

	void OnMouseDown (int (*callback) (Control *sender));
	void OnMouseUp (int (*callback) (Control *sender));
	void OnClose (int (*callback) (Control *sender));

	void FadeTo(unsigned char to_alpha, unsigned int fade_time);

	void SetScriptFunction(int id, char * funcname);
	char * GetScriptFunction(int id);

	void DoOnClose (void);
	void DoOnMouseUp (void);
	void DoOnMouseDown (void);
	void Close(void);

	void SetPage(int);
	int GetPage();

	int getType(void) { return control_type; }

	Control * next;
	MessageStack stack;

	virtual bool CheckPixel(int x, int y);
	virtual Uint32 FindDragContainer(int x, int y, int * drop_x, int * drop_y, Uint32 * charid);

	gui_message CreateCallbackMessage (int type);

	//void ClearControls (void);
	//void AddControl(Control * control);
	//void AddControl(Control * control, int page);
	//Control * GetControl(int controlid);
	//ControlList_t* GetControlList();
	void PeekMessage(MessageStack& stack);

	rect GetRect() const { return rect(x,y,x+width,y+height); }
	void GetRect(rect &rect) const { rect.set_rect(x,y,x+width,y+height); }
	void SetRect(const rect &rect);

	bool IsLayoutValid() { return m_layout_valid; }
	void SetLayoutValid(bool valid) { m_layout_valid = valid; }
	virtual void RecalLayout(GumpHandler * gumps);
protected:
	int x, y, z;
	int width, height;
	int id;
	int focus;
	int flags;
	unsigned char alpha;
	void * tag;
	Control * parent;
	int control_type;

	bool fade;
	unsigned int fade_to;
	unsigned int fade_from;
	unsigned int fade_time;
	unsigned int fade_start;

	int (*callback_OnClose) (Control *sender);
	int (*callback_OnMouseDown) (Control *sender);
	int (*callback_OnMouseUp) (Control *sender);

//	ControlList_t	control_root;
	bool m_layout_valid;
private:
	char * * script_funcs;
	int _data[5];
	int __page;
};


int str2enum(std::string str, const char **enums, int size, int def=0);
inline size get_texture_size(Texture *t) { return t ? size(t->GetRealWidth(), t->GetRealHeight()) : size(0,0); }


}

#endif
