#ifndef UI_BUILDER_H
#define UI_BUILDER_H


#include <string>
#include <vector>
#include <map>
#include "Utils.h"
#include "Variant.h"
#include "Property.h"
#include "XmlParser.h"


#include "Namespace.h"
BEGIN_NAMESPACE


class Widget;


enum WidgetType
{
	WT_VBox,
	WT_HBox,
	WT_Label,
	WT_RadioButton,
	WT_CheckBox,
	WT_Button,
	WT_Slider,
	WT_ComboBox,
	WT_GroupBox,
	WT_LineEdit,
	WT_VSpace,
	WT_HSpace,
	WT_ProgressBar,
	WT_Item,
	WT_Unknown
};


struct TypedWidget
{
	WidgetType m_type;
	Widget*    m_widget;
};


class UiBuilder : public XmlConsumer
{
public:
	UiBuilder(Widget* a_parent);
	~UiBuilder();

	void registerProperty(const char* a_name, AbstractProperty<bool>& a_property) {
		addGenericProperty(a_name, VT_boolean_t, (AbstractProperty<int>*)&a_property);
	}
	void registerProperty(const char* a_name, AbstractProperty<int>& a_property) {
		addGenericProperty(a_name, VT_int32_t, (AbstractProperty<int>*)&a_property);
	}
	void registerProperty(const char* a_name, AbstractProperty<String>& a_property) {
		addGenericProperty(a_name, VT_String, (AbstractProperty<int>*)&a_property);
	}
	// ... add more as appropriate

	// TODO: This is a bad interface as it means the caller knows what the type will be
	// but could be easily changed by changing the XML. Really need a type safe way of
	// doing this. Perhaps if tries to cast it, and does RTTI checks and if it can't cast
	// it, then does something, but what. Problem with loading XML is that it happens at
	// runtime so can't do compile time checks, they need to be dynamic which becomes
	// a bit more work for the programmer to make it correct. Might be better if can
	// avoid the need for this API at all.
	//template <typename T>
	//T* find(const char* a_name) { return (T*)findWidget(a_name); }

	// This returns a widget pointer and it's type. The caller can cast the widget to
	// a specific widget sub-class if they first check the type return is as expected.
	TypedWidget findWidget(const char* a_name);

protected:
	void consumeToken(XmlTokenType a_type, const XmlStringSlice& a_text);
	void addGenericProperty(const char* a_name, VariantType a_type, AbstractProperty<int>* a_property);
private:
	class UiBuilderData* m_data;
};


END_NAMESPACE


#endif // UI_BUILDER_H

