/*
 *  psychlops_widgets_prototype.h
 *  Psychlops Standard Library (Universal)
 *
 *  Last Modified 2006/12/08 by Kenchi HOSOKAWA
 *  (C) 2006 Kenchi HOSOKAWA, Kazushi MARUYA and Takao SATO
 */

#ifndef HEADER_PSYCHLOPS_WIDGETS_PROTOTYPE
#define HEADER_PSYCHLOPS_WIDGETS_PROTOTYPE

#include <vector>
#include <deque>
#include <sstream>

#include "psychlops_widget.h"
#include "../figure/psychlops_figure_standard.h"
#include "../../../psychlops_core.h"


namespace Psychlops {
namespace Widgets {


	bool hook(Figure *f, bool on_off, Canvas *cnvs = dynamic_cast<Canvas *>(Drawable::prime));

	// This is prototype class. Don't derive from this class.
	class RectWidget : public Rectangle {
		public:
		RectWidget();
/*		RectWidget(const double width, const double height);
		virtual ~RectWidget();
		virtual RectWidget& set(const double width, const double height);
*/
/*		virtual RectWidget& centering(const Drawable& target = *Drawable::prime);
		virtual RectWidget& centering(const Point& p);
		virtual RectWidget& centering(const double x, const double y, const double z = 0);
		virtual RectWidget& shift(const double x, const double y, const double z = 0);
*/
	};


	// This is prototype class. Temporary use only.
	class Console : public RectWidget {
		private:
		bool changed_;
		struct LetterStyle {
			int line_height_;
			LetterStyle();
		} paragraph_style_;
		std::stringstream strings_;
		std::deque<std::string> lines_;
		struct LineView {
			std::string *target;
			int begin, end;
			LineView();
			LineView(std::string &t, int b, int e);
		};
		std::deque<LineView> view_;
		int last_pos_;
		char *buffer;

		public:
		Color textColor;

		Console();
		Console(const Rectangle &rect);
		Console(const double width, const double height);
		virtual ~Console();
		virtual Console & set(const Rectangle &rect);
		virtual Console & set(const double width, const double height);
		virtual Console & hook(bool on_off = true, Canvas *cnvs = dynamic_cast<Canvas *>(Drawable::prime));
		virtual Console & draw(Drawable &target = *Drawable::prime);
		virtual Console & draw(const Color &col, Drawable &target = *Drawable::prime);
		virtual Console & draw(const Stroke &strk, Drawable &target = *Drawable::prime);
		virtual Console & draw(const double x, const double y, const double z = 0, Drawable &target = *Drawable::prime);
		virtual void save(std::string filename);

		template <typename X> Console & operator <<(X arg) {
			strings_ << arg;
			changed_ = true;
			return *this;
		};
		virtual void devideStreamIntoLines();
	};



	class HotKeyWidget : public Widget {
	protected:
		Keyboard::Key key;
		void (*func)();
	public:
		HotKeyWidget(const Keyboard::Key &init_key = Keyboard::spc);
		virtual ~HotKeyWidget();
		virtual const Point getDatum() const;
		virtual HotKeyWidget& setDatum(const Point &p);
		virtual HotKeyWidget& centering(const Point &p);
		virtual HotKeyWidget& draw(Drawable &drawable = *Drawable::prime);
	};

	class PauseHotKey : public HotKeyWidget {
		public:
		PauseHotKey(const Keyboard::Key &init_key = Keyboard::spc);
		virtual PauseHotKey& draw(Drawable &target = *Drawable::prime);
	};

	class ExitHotKey : public HotKeyWidget {
		public:
		ExitHotKey(const Keyboard::Key &init_key = Keyboard::esc);
		virtual ExitHotKey& draw(Drawable &target = *Drawable::prime);
	};

	class TabStopHotKey : public HotKeyWidget {
		bool registered;
		public:
		TabStopHotKey();
		TabStopHotKey(const Keyboard::Key &init_key);
		virtual void set(void* target);
		virtual TabStopHotKey& draw(Drawable &target = *Drawable::prime);

		static TabStopHotKey tabStopHotKey;
	};


	class MoviePlayer
	{
	protected:
		static bool auto_play;
		static MoviePlayer *now_playing;
		static Prototype::Thread thread;
		static Canvas *cnvs;
		static Canvas::CanvasMode mode;
		static Display *disp;
		static void play_loop();
		static void play_loop_in_this_thread();

		static void paraThread();

	public:
		std::deque< Figures::Movie* > movies;

		MoviePlayer();
		MoviePlayer(Figures::Movie &movie);
		~MoviePlayer();

		void appendMovie(Figures::Movie &movie);

		//void start(Canvas::CanvasMode mode = Canvas::fullscreen, const Display &disp = Display::primary);	// create another thread and canvas
		//void start(Canvas::CanvasMode mode, const Display &disp);	// create another thread and canvas
		void start(Canvas& target = *Display::the_canvas); // create another thread
		void start(void (*func)(), Canvas& target = *Display::the_canvas); // create another thread
		void stop();
	};


	class SequentialScreenshot : public RectWidget {
		protected:
		int max_shot, current_shot;
		bool saved;
		bool rec;

		public:
		Rectangle source;
		static std::string bin_path;
		std::string directory, filePrefix;
		std::vector<Image*> movie;

		SequentialScreenshot();
		SequentialScreenshot(const Rectangle &rect);
		virtual ~SequentialScreenshot();
		virtual SequentialScreenshot& set(const Rectangle &rect);
		virtual SequentialScreenshot& set(const double width, const double height);
		virtual SequentialScreenshot& clear();
		virtual SequentialScreenshot& hook(bool on_off = true, Canvas *cnvs = dynamic_cast<Canvas *>(Drawable::prime));
		virtual SequentialScreenshot& record(int max_num_shots=0, std::string file_prefix = "%EXPNAME__%TIME_");
		virtual const SequentialScreenshot& stop();
		virtual const SequentialScreenshot& save();
		virtual const SequentialScreenshot& save(std::string filename);

		virtual SequentialScreenshot& draw(Drawable &target = *Drawable::prime);
	};
	extern SequentialScreenshot default_screenshot;

/*
	class Movie : public Widget {
		protected:
		int max_shot, current_shot;
		bool saved;
		bool rec;

		public:
		Rectangle source;
		std::string directory, filePrefix;
		std::vector<Image*> movie;
		size_t current_frame;

		Movie();
		Movie(const Rectangle &rect);
		virtual ~Movie();
		virtual Movie& set(const Rectangle &rect);
		virtual Movie& set(const double width, const double height);
		virtual Movie& load(size_t begin = 0, size_t end = -1);
		virtual Movie& load(const char* format, size_t begin = 0, size_t end = -1);
		virtual Movie& clear();
		virtual Movie& hook(bool on_off = true, Canvas *cnvs = dynamic_cast<Canvas *>(Drawable::prime));
		virtual Movie& record(int max_num_shots=0, std::string file_prefix = "%EXPNAME__%TIME_");
		virtual Movie& seek(size_t frame);
		virtual Movie& stop();
		virtual const Movie& save(size_t begin = 0, size_t end = -1);
		virtual const Movie& save(const char* format, size_t begin = 0, size_t end = -1);

		virtual Movie& draw(Drawable &target = *Drawable::prime);
		virtual Movie& play(Drawable &target = *Drawable::prime);
	};
*/


	// This is prototype class. Temporary use only.
	class TextInput : public RectWidget {
		private:
		public:
		TextInput();
	};




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


#endif
