#include <psychlops.h>
using namespace Psychlops;	// Initially developed with Psychlops Win32 1.4.6 / 20100325


const char *default_glsl =
			"void main(void){ "
			"float phase = gl_TexCoord[4][3], contrast = gl_TexCoord[4][0], orientation = gl_TexCoord[4][2], frequency = 2.0*PI/gl_TexCoord[4][1];"
			"float _x = sin(orientation)*xp()-cos(orientation)*yp();"
			"pix(0.5 + contrast*0.5*cos(frequency*_x + phase) ,0.0,0.0,1.0); }";

Figures::ShaderField field;
char *source = (char*)default_glsl;

void cache(const std::string path)
{
	char one;
	std::stringstream buf;
	std::ifstream is;
	is.open(path.c_str(), std::ifstream::in);
	if(is.fail()) {
		Widgets::Dialog::alert(L"File was not found, or failed to read for some reasons.");
		return;
	}
	while(is.good())	{
		is.get(one);
		buf << one;
	}
	std::cout << buf.str();

	try{
		field.setFunction(buf.str().c_str());
		field.cache(*Display::the_canvas);
	} catch (Exception e) {
		Widgets::Dialog::alert(e.to_s());
	} catch (Exception *e) {
		Widgets::Dialog::alert(e->to_s());
	}
}




class RangedSlider : public Widgets::WidgetRect
{
	public:
	static Interval itvl[6];
	static void initialize() {
		0<=itvl[0]<=1;
		-1<=itvl[1]<=1;
		0<=itvl[2]<=100;
		-100<=itvl[3]<=100;
		0<=itvl[4]<=2*PI;
		-2*PI<=itvl[5]<=2*PI;
	}
	Widgets::Slider slide;
	Widgets::SelectBox box;
	RangedSlider& set(std::wstring lab, double hei) {
		const Color ic(0,0,1,0.7), oc(.5,.5,.5,.5);
		slide.set(lab, hei);
		slide.area.fill = oc;
		slide.internal.fill = ic;
		box.append(L"[0, 1]");
		box.append(L"[-1, 1]");
		box.append(L"[0, 100]");
		box.append(L"[-100, 100]");
		box.append(L"[0, 2PI]");
		box.append(L"[-2PI, 2PI]");
		area.set(slide.getWidth()/3, hei);
		return *this;
	}
	RangedSlider& draw(Drawable &target = *Drawable::prime)
	{
		if(box.pushed()) {
			double ratio = slide.getRatio();
			slide.setInterval(itvl[box.getSelected()]);
			slide.setByRatio(ratio);
		}
		slide.area.set(getWidth()*2/3.0, getHeight()).alignLeft(getLeft()).alignTop(getTop());
		slide.draw(target);
		box.area.set(getWidth()/3.0, getHeight()).alignRight(getRight()).alignTop(getTop());
		box.draw(target);
		return *this;
	}
};
Interval RangedSlider::itvl[6];


void ShaderTestTool() {

	Canvas cnvs(Canvas::fullscreen);


	Widgets::Button loader(L"Load GLSL", 18);
	loader.centering(cnvs.getWidth()-loader.area.getWidth()/2-20, cnvs.getHeight() - 20);
	Drawable::billboard.append(loader);

	std::string path;
	Letters pathname;
	pathname.font.size = 15;
	pathname.locate(loader.area.getLeft() - 20, loader.area.getBottom()-2).align = Letters::TEXT_ALIGN_RIGHT;

//	field.setFunction(buffer);
//	field.cache(*Display::the_canvas);
	field.cache(default_glsl, *Display::the_canvas);

	Psychlops::Rectangle area(300,300);
	area.centering();

	double Z[12];
	for(int i=0; i<12; i++) Z[i] = 0.0;

	RangedSlider sliders[12];
	RangedSlider::initialize();
	Widgets::StackPanel panel;
	std::stringstream wss;
	for(int i=0; i<12; i++) {
		wss.str("");
		wss << "var[" << i << "] ";
		sliders[i].set(L"0", 18);
		sliders[i].slide.label.setString(wss.str().c_str());
		sliders[i].slide.link(Z[i], RangedSlider::itvl[0], 1);
		panel.append(&sliders[i]);
	}
	panel.set(200,500).shift(10,10);

	int error;

	while(!Input::get(Keyboard::esc)) {
		Display::clear();

		if(loader.pushed()) {
			try {
				path = Widgets::Dialog::getOpenFileName();
				cache(path);
				path.append("   OK ");
				pathname.fill = Color::yellow;
				error = 1;
			} catch(Exception e) {
				path = e.to_s();
				pathname.fill = Color::red;
				error = -1;
			}
			pathname.setString(path.c_str());
		}

		field.draw(area, Z, 3, *Display::the_canvas);
		//for(int i=0; i<12; i++) { sliders[i].draw(); }
		panel.draw();
		pathname.draw();
		Display::flip();
		if(AppState::shouldBeClose) return;
	}

}


void psychlops_main() {
	Procedure p;
	p.setDesign(Procedure::DEMO);
	p.setProcedure(ShaderTestTool);
	p.run();

}

