/*
 * Theme.h
 *
 *  Created on: 2009-07-11
 *      Author: wasyl
 */

#ifndef THEME_H_
#define THEME_H_

#include <cmath>
#include <allegro5/allegro.h>
#include <allegro5/a5_primitives.h>
#include <allegro5/a5_opengl.h>
#include "../prep/misc/Random.h"
#include "../prep/misc/Vector2D.h"

class Theme
{
	static Theme *themes[6];
	static Theme *current;

public:
	static void initialize();
	static Theme &active() { return *current; }
	static void set(int i) { current = themes[i]; }
	static Theme &get(int i) { return *themes[i]; }

	virtual ALLEGRO_COLOR gradientUp() = 0;
	virtual ALLEGRO_COLOR gradientDown()  = 0;
	virtual ALLEGRO_COLOR cloudColor() = 0;
	virtual void preProcess(){};
	virtual void postProcess(){};
	virtual void update(double dt){};
	virtual const char *name() = 0;
	virtual bool behind() { return randomInt(0,2); }
	virtual int unlockPoints() { return 0; }
};

class ThStandard : public Theme
{
	virtual ALLEGRO_COLOR gradientUp()   { return al_map_rgb_f(0.58f,0.85f,1.0f); }
	virtual ALLEGRO_COLOR gradientDown() { return al_map_rgb_f(0.3f, 0.55f,1.0f); }
	virtual ALLEGRO_COLOR cloudColor()   { return al_map_rgba(255,255,255,128); }
	virtual const char *name()           { return "Sky"; }
};

class ThSunset : public Theme
{
	virtual ALLEGRO_COLOR gradientUp()   { return al_map_rgb(230,130,30); }
	virtual ALLEGRO_COLOR gradientDown() { return al_map_rgb(230,70, 70); }
	virtual ALLEGRO_COLOR cloudColor()   { return al_map_rgba(255,220,220,128); }
	virtual const char *name()           { return "Sunset"; }
	int unlockPoints() { return 6; }
};

class ThCrooked : public Theme
{
	virtual ALLEGRO_COLOR gradientUp()   { return al_map_rgb_f(0.58f,0.85f,1.0f); }
	virtual ALLEGRO_COLOR gradientDown() { return al_map_rgb_f(0.3f, 0.55f,1.0f); }
	virtual ALLEGRO_COLOR cloudColor()   { return al_map_rgba(255,255,255,128); }
	virtual const char *name()           { return "Crooked"; }
	void preProcess()
	{
		glTranslatef(0.0f, -20.f, 0.0f);
		glRotatef(5.625f, 0.0, 0.0, 1.0);
	}
	void postProcess()
	{
		glTranslatef(0.0f, 20.f, 0.0f);
		glRotatef(-5.625f, 0.0, 0.0, 1.0);
	}
	int unlockPoints() { return 24; }
};

class ThMist : public Theme
{
private:
	double mTime;

public:
	virtual ALLEGRO_COLOR gradientUp()   { return al_map_rgb_f(0.85f,0.85f,0.85f); }
	virtual ALLEGRO_COLOR gradientDown() { return al_map_rgb_f(0.45f,0.45f,0.45f); }
	virtual ALLEGRO_COLOR cloudColor()   { return al_map_rgba(200,200,200,128); }
	virtual const char *name()           { return "Mist"; }
	void postProcess()
	{
		glBegin(GL_QUADS);
			glColor4f(1.0f,1.0f,1.0f,0.0f); glVertex2f(0.0f, 600.0f); glVertex2f(800.0f, 600.0f);
			glColor4f(1.0f,1.0f,1.0f,0.7f); glVertex2f(800.0f, 200.0f); glVertex2f(0.0f, 200.0f);
			glVertex2f(0.0f, 200.0f); glVertex2f(800.0f, 200.0f);
			glVertex2f(800.0f, 0.0f); glVertex2f(0.0f, 000.0f);
		glEnd();
	}
	bool behind() { return false; }
	virtual void update(double dt){mTime += dt;};
	int unlockPoints() { return 12; }
};

class ThSway : public Theme
{
private:
	double mTime;

public:
	virtual ALLEGRO_COLOR gradientUp()   { return al_map_rgb_f(0.58f,0.85f,1.0f); }
	virtual ALLEGRO_COLOR gradientDown() { return al_map_rgb_f(0.3f, 0.55f,1.0f); }
	virtual ALLEGRO_COLOR cloudColor()   { return al_map_rgba(255,255,255,128); }
	virtual const char *name()           { return "Liquor"; }
	void preProcess()
	{
		glPushMatrix();
		glTranslatef(0.0f, std::sin(mTime) * 10.0f - 10.0f, 0.0f);
		glRotatef(std::sin(mTime*0.25)*5.625f, 0.0, 0.0, 1.0);
	}
	void postProcess()
	{
		glPopMatrix();
	}
	virtual void update(double dt){mTime += dt;};
	int unlockPoints() { return 30; }
};

class ThNight : public Theme
{
private:
	Vec starPos[100];
public:
	ThNight()
	{
		for (int i = 0; i < 100; i++)
			starPos[i] = Vec(randomFloat(3.0, 797.0), randomFloat(3.0, 597.0));
	}
	virtual ALLEGRO_COLOR gradientUp()   { return al_map_rgb(40, 10, 60); }
	virtual ALLEGRO_COLOR gradientDown() { return al_map_rgb(10, 0, 20); }
	virtual ALLEGRO_COLOR cloudColor()   { return al_map_rgb(0, 0, 0); }
	bool behind() { return true; }
	virtual const char *name()           { return "Night"; }
	void preProcess()
	{
		for (int i = 0; i < 100; i++)
			al_draw_pixel(starPos[i].x, starPos[i].y, al_map_rgb(128, 128, 128));
	}
	void postProcess()
	{
		al_set_blender(ALLEGRO_ALPHA, ALLEGRO_INVERSE_ALPHA, al_map_rgba(0,0,0,80));
		al_draw_filled_rectangle(0.0, 0.0, 800.0, 600.0, al_map_rgb(0,0,0));
		al_set_blender(ALLEGRO_ALPHA, ALLEGRO_INVERSE_ALPHA, al_map_rgba(255,255,255,255));
	}
	int unlockPoints() { return 18; }
};

#endif /* THEME_H_ */
