/*
 *  psychlops_widgets_prototype.h
 *  Psychlops Standard Library (Universal)
 *
 *  Last Modified 2009/02/15 by Kenchi HOSOKAWA
 *  (C) 2009 Kenchi HOSOKAWA, Kazushi MARUYA, Takao SATO
 */

#ifndef HEADER_PSYCHLOPS_WIDGETS
#define HEADER_PSYCHLOPS_WIDGETS

#include <string>
#include "../../../core/graphic/psychlops_g_module.h"
#include "../../../psychlops_core.h"
#include "../psychophysics/psychlops_exp_psychophysics.h"
#include "psychlops_widgets_event.h"
#include "psychlops_widget.h"


namespace Psychlops {


namespace Widgets {

	class TextBlock : public WidgetBase
	{
		protected:
		bool initialized;
		void initialize();
		Letters label;
		std::wstring content;

		public:
		TextBlock();
		TextBlock(std::wstring s, double hei = Font::default_font.size);
		virtual Point getHitDatum();
		//virtual Rectangle getArea();
		virtual TextBlock& set(std::wstring s, double hei = Font::default_font.size);
		virtual TextBlock& set(double w, double h);
		void setText(const std::wstring &str);
		std::wstring& getText();
	};


	class Button_ : public TextBlock {
	protected:
		void (*onClick)();
		void evokeP(Events::Evoke &);
		void evokeMouse(Events::MouseLeftUp &e);
	public:
		Button_();
		Button_(std::wstring s, double size = 0);
		//virtual Button_& set_(std::wstring s, double hei = Font::default_font.size);
		//virtual Button_& set_(double w, double h);
		virtual void onEvoked(void (*f)());
	};













	class TextBox : public WidgetRect {
	protected:
		void setBase();
		Letters cache;
		std::wstring content;
	public:
		TextBox();
		TextBox(std::wstring s);
		virtual TextBox& set(std::wstring s);
		virtual TextBox& draw(Drawable &target = *Drawable::prime);
		void setText(const std::wstring &str);
		std::wstring& getText();
	};

	class Button : public WidgetRect {
	protected:
		void (*onClick)();
		void (*onClickP)(void *);
		void setBase();
	public:
		void *arg;
		Button();
		Button(std::wstring s);
		Button(std::wstring s, double size);
		virtual Button& set(std::wstring s, double hei = Font::default_font.size);
		virtual Button& set(double w, double h);
		virtual Button& draw(Drawable &target = *Drawable::prime);
	};

	class ToggleButton : public Button {
	protected:
		bool checked_;
	public:
		ToggleButton();
		ToggleButton(std::wstring s);
		ToggleButton(std::wstring s, double size);
		bool toggle();
		bool toggle(bool on_off);
		bool isChecked();
		virtual ToggleButton& draw(Drawable &target = *Drawable::prime);
	};

	class ScreenShotButton : public Button {
	protected:
		static void shoot(void *fname);
		static Image buffer;
	public:
		std::string name;
		ScreenShotButton(char *name);
	};

	class Slider : public WidgetRect {
	protected:
		bool dragged;
		double local;
		bool isLocal_;
		ExperimentalMethods::Variable *var;
		bool changed_;
		void setBase();
	public:
		enum ScaleMode { LINEAR, LOG };
		ScaleMode scale_mode;
		static const Interval def_itvl;
		Rectangle internal;
		bool show_value;

		Slider();
		~Slider();
		Slider(ExperimentalMethods::Variable &v);
		Slider(double wid, double hei);
		Slider(std::string s, Interval rng = def_itvl, double d_step = 0.1, double e_step = 1);
		template<typename T, typename S> Slider(T &item, std::string s, Interval rng = def_itvl, S d_step = 0.1, S e_step = 0.05)
		{
			setBase();
			set(s);
			link(s, item, rng, d_step, e_step);
		}
		virtual Slider& set(ExperimentalMethods::Variable &v);
		virtual Slider& set(std::string s, Interval rng = def_itvl, double d_step = 0.1, double e_step = 0.05);
		virtual Slider& setSize(double wid, double hei);
		virtual Slider& setLabel(std::string s);
		virtual Slider& setLabel(std::wstring s);
		//virtual Slider& setLabel(std::string s, double hei = Font::default_font.size);
		//virtual Slider& setLabel(std::wstring s, double hei = Font::default_font.size);
		virtual Slider& draw(Drawable &target = *Drawable::prime);
		Slider& linkTo(ExperimentalMethods::Variable *v);
		Slider& operator =(ExperimentalMethods::Variable &v);
		template<typename T, typename S> Slider& link(T &item, Interval rng = def_itvl, S d_step = 0.1, S e_step = 0.05) { return link(item, " ", rng, d_step, e_step); }
		template<typename T, typename S> Slider& link(T &item, std::string s, Interval rng = def_itvl, S d_step = 0.1, S e_step = 0.05)
		{
			setLabel(s);
			ExperimentalMethods::VariableInstance<T>* v = new ExperimentalMethods::VariableInstance<T>(&item);
			v->set(s, rng, d_step, e_step);
			var = v;
			isLocal_ = true;
			StackPanel::default_stack.remove(this);
			return *this;
		}
		bool changed();
		operator double();
		double operator =(double v);
		void setByRatio(double ratio);
		double getRatio() const;
		Interval getInterval() const;
		Interval setInterval(const Interval &itvl);
		void increment(int modulation = 0);
		void decrement(int modulation = 0);
	};

	class Dial : public WidgetDatum {
	protected:
		Rectangle ext, internal;
		Letters let;
		double current_theta, former_theta, factor;
		double local;
		double *var;
		bool pressed, dragged;
		bool changed_;
	public:
		Dial();
		Dial(double r);
		void setBase();
		Dial& label(std::wstring s);
		Dial& set(double r);
		Dial& draw(Drawable &target = *Drawable::prime);
		Dial& link(double &item, double fac = 1);
		bool changed();
		operator double();
		double operator =(double v);
	};

	class SelectBox : public WidgetRect
	{
		protected:
		std::deque<Letters> item;
		int selected_;
		bool vertical_;
		Group holder_;
		void appendL(Letters &let);

		public:
		SelectBox();
		SelectBox(double hei);
		SelectBox& set(double hei);
		SelectBox& set(double wid, double hei);
		void makeVertical();
		template<class T> void append(T arg)
		{
			Letters let(arg);
			appendL(let);
		}
		int getSelected();
		void setSelected(int dd);
		void next();
		void retreat();
		void hid();
		virtual SelectBox& draw(Drawable &target = *Drawable::prime);
	};


	class CloseButton : public Button
	{
		protected:
		public:
		CloseButton();
		static void exitApp();
	};

	class MinimizeButton : public Button
	{
		protected:
		Canvas* window;
		public:
		MinimizeButton(Canvas &target);
		static void minimizeApp(void *hwnd);
	};

	class TitleBar : public WidgetDatum
	{
	public:
		static TitleBar *default_titlebar;

	protected:

		CloseButton close;
		MinimizeButton minimize;
		Rectangle area;
		HumanInterfaceDevice::ButtonStateHolder mleft;
		Point begin_m, begin_w, begin_w_size;

		bool dragged_;
		public:
		TitleBar(Canvas &target);
		TitleBar& draw(Drawable &target = *Drawable::prime);
	};


namespace Dialog {

	void alert(std::string message);
	void alert(std::wstring message);
	std::string getOpenFileName();

}	/*	<- namespace Dialog 	*/


}	/*	<- namespace Widgets 	*/
}	/*	<- namespace Psycholops 	*/


#endif
