#ifndef _TK_BASE_H_
#define _TK_BASE_H_

#include "../../tinyxml/tinyxml.h"

#include "options/options.h"

#include "../tcl_guid.h"
#include "../vars.h"
#include "../tcl_interp.h"
#include "../../ptr.h"
#include "../../txmlobject.h"

#include "event/eactivate.h"
#include "event/ebuttonpress.h"
#include "event/ebuttonrelease.h"
#include "event/ecirculate.h"
#include "event/ecirculaterequest.h"
#include "event/ecolormap.h"
#include "event/econfigure.h"
#include "event/econfigurerequest.h"
#include "event/ecreate.h"
#include "event/edeactivate.h"
#include "event/edestroy.h"
#include "event/edouble.h"
#include "event/eenter.h"
#include "event/eexpose.h"
#include "event/efocusin.h"
#include "event/efocusout.h"
#include "event/egravity.h"
#include "event/ekeypress.h"
#include "event/ekeyrelease.h"
#include "event/eleave.h"
#include "event/emap.h"
#include "event/emaprequest.h"
#include "event/emotion.h"
#include "event/emousewheel.h"
#include "event/eproperty.h"
#include "event/ereparent.h"
#include "event/eresizerequest.h"
#include "event/eunmap.h"
#include "event/evisibility.h"

#include <string>
#include <list>
#include <map>

using namespace std;
using namespace event;

class TkContainer;
class TkTopLevel;

/**
 * \brief Base class for all type of widgets
 *
 * \date 01-11-2006
 *
 * \author Ondrej Svejdar
 *
 * \todo 
 *
 * \bug 
 *
 */
class TkBase:public TXmlObject,
	public EActivate,
	public EButtonPress,
	public EButtonRelease,
	public ECirculate,
	public ECirculateRequest,
	public EColormap,
	public EConfigure,
	public EConfigureRequest,
	public ECreate,
	public EDeactivate,
	public EDestroy,
	public EDouble,
	public EEnter,
	public EExpose,
	public EFocusIn,
	public EFocusOut,
	public EGravity,
	public EKeyPress,
	public EKeyRelease,
	public ELeave,
	public EMap,
	public EMapRequest,
	public EMotion,
	public EMouseWheel,
	public EProperty,
	public EReparent,
	public EResizeRequest,
	public EUnmap,
	public EVisibility
{
	TkContainer* parent;
	Tk_Window obj;
	Tk_Window mainWindow;
	Tk_Uid id;

	string name;

	Ptr<TXmlObject> constraints;
	Ptr<TXmlObject>	tag;

	void bindEvents();
	bool eventsEnabled;
public:
	typedef map<const Ptr<TkOptionDef>,Ptr<TXmlObject> > t_option_set;
	const static Ptr<TkOptionDef> OPT_END;
protected:
	Ptr<TclInterp> interp;

	TclGuid guid;

	t_option_set bcOptionSet;
	t_option_set optionSet;
	
	bool created;
	bool displayed;

	const string& getCurrentName() const;

	virtual void baseClone(TkBase* obj);

	void doSerialize(TiXmlElement& element) const;
	void doDeserialize(const TiXmlElement& element);
public:
	/**
	 * \brief Return layout constraints (if any)
	 *
	 * In case there aren't any returns empty TXmlObject
	 * \return layout constraints
	 */
	Ptr<TXmlObject>& getConstraints();


	/**
	 * \brief Set layout constrains
	 * \param constraints layout constrainst
	 */
	void setConstraints(Ptr<TXmlObject>& constraints);
	
	
	/**
	 * \brief Forces layout to redisplay widget.
	 *
	 * Does nothing if widget is not displayed.
	 */
	void invalidate();

	/**
	 * \brief Returns reference to interpret, in which was widget created
	 * \return reference to interpret
	 */
	Ptr<TclInterp>& getInterp();

	
	/**
	 * \brief Returns option set
	 * \return option set
	 */
	const t_option_set& getOptionSet() const;


	/**
	 * \brief Test if widget is created
	 * \return true if widget created in shell
	 */
	bool isCreated() const;


	/**
	 * \brief Returns Tk identifier of the widget window 
	 *
	 * That means toplevel window in which is widget placed.
	 * \return Tk widget identifier
	 */
	Tk_Window getWindow() const;

	/**
	 * \brief Returns parent of widget (if any) otherwise NULL
	 * \return pointer to parent widget
	 */
	TkContainer* getParent();

	/**
	 * \brief Returns Tk unique widget identifier.
	 * \note This uid is sequenceof chars, equal to widget's name.
	 * Tk uses reference comparsion to hurry things up. 
	 * \return widget uid 
	 */
	Tk_Uid getUid() const;

	/**
	 * \brief Returns unique ID, generated for widget.
	 * \return widget generated id
	 */
	const string& getGeneratedId() const
	{
		return guid.getId();
	}

	/**
	 * \brief Return user-defined name for widger
	 * \return name of widget
	 */
	const string& getName() const;

	/**
	 * \brief Returns type of widget.
	 *
	 * Example values are "button","menu","entry" etc.
	 * \return widget type
	 */
	virtual const char* getTkClass() const=0;


	/**
	 * \brief Returns array of all avaliable options valid for specific widget type
	 * \return array of options
	 */
	virtual const Ptr<TkOptionDef>* getOptionAll() const=0;

	bool compareTo(TObject* object) const
	{
		return ((TkBase*)object)->id==id;
	}

	TObject* clone()=0;

	/**
	 * \brief Return tag
	 *
	 * Each instance of class TkBase can have one "general purpose" object - tag,
	 * it is free to use for application programmer.
	 *
	 * \return reference to tag (if any) or empty object
	 */
	Ptr<TXmlObject>& getTag();


	/**
	 * \brief Sets tag
	 * \param tag value
	 */
	void setTag(TXmlObject* tag);

	/**
	 * \param interp interpreter 
	 */
	TkBase(Ptr<TclInterp>& interp);
	
	/**
	 * \brief Creates widget in shell
	 */
	virtual void create();

	/**
	 * \brief Sets value of one widget property
	 * \param def option definition, definition of this property
	 * \param option value
	 */
	void setOption(const Ptr<TkOptionDef>& def,TXmlObject* option);
		
	/**
	 * \brief Returns value of one widget property as Tcl_Obj
	 * \param def property definition, usually static member of specific widget
	 * \return property value
	 */
	Tcl_Obj* getOption(const Ptr<TkOptionDef>& def) const;

	/**
	 * \brief Works just like getOption, but result is presented as string
	 * \param def property definition, usually static member of specific widget
	 * \return property value
	 */
	const string& getStrOption(const Ptr<TkOptionDef>& def) const;
	
	/**
	 * \brief Set widget property in raw (string) format. Should be avoided.
	 * \param optionName name of property 
	 * \param value value
	 */
	void setRawOption(const string& optionName,const string& value);
	
	
	/**
	 * \brief Set user-defined name for widget
	 * \param name user-defined name for widget
	 */
	void setName(const string& name);


	/**
	 * \brief Enables or disables events on widget.
	 * \param value if true events will be enabled
	 */
	virtual void setEventsEnabled(bool value);
	
	
	/**
	 * \brief Returns state of event generation
	 * \return true if events are enabled
	 */
	bool isEventsEnabled() const;
	const string& toString() const;

	/**
	 * \brief Set background color.
	 * \param color color value
	 */
	virtual void setBackgroundColor(TkColorOption* color)=0;
	
	
	/**
	 * \brief Returns background color of widget
	 * \return background color
	 */
	virtual Ptr<TkColorOption>& getBackgroundColor() const=0;

	friend class TkContainer;
	friend class TkTopLevel;
};

/**
 * \brief Common interface implemented by all widgets with at least two states - normal and disabled.
 *
 * \date 01-12-2006
 *
 * \author Ondrej Svejdar
 *
 * \todo 
 *
 * \bug 
 *
 */
class IStateable
{
public:
	virtual bool isEnabled() const=0;
    virtual void setEnabled(bool value)=0;
};

/**
 * \brief Common interface implemented by all widgets with text-like content.
 *
 * \date 01-12-2006
 *
 * \author Ondrej Svejdar
 *
 * \todo 
 *
 * \bug 
 *
 */
class ITextable
{
public:
	/**
	 * \brief Gets content of widget in text form
	 * \return text content
	 */
	virtual const string& getText() const=0;

	/**
	 * \brief Sets text of widget
	 * \param text text to set
	 */
	virtual void setText(const string& text)=0;
};

class TkScrollBar;

/**
 * \brief Common interface implemented by all widgets with horizontal scrollbar.
 *
 * \date 01-12-2006
 *
 * \author Ondrej Svejdar
 *
 * \todo 
 *
 * \bug 
 *
 */
class IXScroll
{
protected:
	TkScrollBar* xbar;
	void createXBar(Ptr<TclInterp>& interp,TkBase* self,const Ptr<TkOptionDef>& optXScroll);
public:
	IXScroll();
	/**
	 * \brief Add horizontal scrollbar
	 * \param bar scrollbar to add
	 */
	void setXScrollBar(TkScrollBar* bar);
};

/**
 * \brief Common interface implemented by all widgets with vertical scrollbar.
 *
 * \date 01-12-2006
 *
 * \author Ondrej Svejdar
 *
 * \todo 
 *
 * \bug 
 *
 */
class IYScroll
{
protected:
	TkScrollBar* ybar;
	void createYBar(Ptr<TclInterp>& interp,TkBase* self,const Ptr<TkOptionDef>& optYScroll);
public:
	IYScroll();
	/**
	 * \brief Add vertical scrollbar
	 * \param bar 
	 */
	void setYScrollBar(TkScrollBar* bar);
};

/**
 * \brief Common interface implemented by all widgets with default inner variable.
 * 
 * \date 01-31-2006
 *
 * \author Ondrej Svejdar
 *
 * \todo 
 *
 * \bug 
 *
 */
class IInnerVariable
{
public:
	/**
	 * \brief return pointer to default variable
	 * \return pointer to default variable
	 */
	virtual TclVar* getDefaultVar()=0;
};

#endif/*_TK_BASE_H_*/
