module vs.scene.interval;



private import std.math;
private import gedo.gui.label;
private import gedo.gui.cursor;
private import gedo.gui.component;
private import gedo.audio.sound;
private import gedo.audio.music;
private import gedo.video.ggl;
private import gedo.video.rect;
private import gedo.video.color;
private import gedo.video.texture;
private import gedo.video.staticmesh;
private import gedo.input.joystick;
private import gedo.system.scene;
private import vs.scene.action;
private import vs.action.field;
private import vs.scene.characterselect;



private const float[2] CANVAS_SIZE = [640, 480];
private const float[2] SELECTEDITEM_SIZE = [128, 256];



private enum OperatorID
{
	P1,
	P2,
	CP,
}



alias Scene delegate() OnQuit;



public class Interval : Scene
{
public:
	this(OnQuit dg, int stage, CharacterID[] ids, Player2is p2is)
	{
		_onQuit = dg;

		_wallPaper = new WallPaper(stage);

		{
			StaticMesh[2][2] buffer;

			buffer[0][0] = StaticMesh("$LIB/characterselect/p1.gsa");
			switch(p2is)
			{
			case Player2is.NONE:
				buffer[0][1] = StaticMesh("$LIB/characterselect/cp.gsa");
				buffer[1][0] = buffer[0][1];
				buffer[1][1] = buffer[0][1];
				break;

			case Player2is.FRIEND:
				buffer[0][1] = StaticMesh("$LIB/characterselect/p2.gsa");
				buffer[1][0] = StaticMesh("$LIB/characterselect/cp.gsa");
				buffer[1][1] = buffer[1][0];
				break;

			case Player2is.ENEMY:
				buffer[0][1] = StaticMesh("$LIB/characterselect/cp.gsa");
				buffer[1][0] = StaticMesh("$LIB/characterselect/p2.gsa");
				buffer[1][1] = buffer[0][1];
				break;
			}

			auto se = Sound("$LIB/cursor_click.ogg");
			float x = -CANVAS_SIZE[0]*0.5 + CANVAS_SIZE[0]/8.0;
			foreach(it, inout t; _selectedItems)
			{
				foreach(ip, inout p; t)
				{
					auto a = it*2 + ip;

					p = new SelectedItem(x, 0.0, buffer[it][ip], ids[a], a*8, se);

					x += CANVAS_SIZE[0]/4.0;
				}
			}
		}

		_player2is = p2is;
		_time      = 60*5;
	}


	override void update()
	{
		foreach(t; _selectedItems)
		{
			foreach(p; t)
			{
				p.update();
			}
		}

		_wallPaper.update();

		if(_time <= 0)
		{
			_nextScene = _onQuit();
		}
		else
		{
			if(_time < 60*4 && Joysticks().detectPressed())
			{
				_time = 0;
			}
			else
			{
				--_time;
			}
		}
	}


	override void draw()
	{
		GGL_enableDepthBuffer(0);

		GGL_enableAlphaBlend(1);

		GGL_enter2DMode(CANVAS_SIZE[0], CANVAS_SIZE[1]);

		_wallPaper.draw();

		Color[2] teamColors;

		teamColors[0] = rgba(255, 0, 0, 128);
		teamColors[1] = rgba(0, 255, 0, 128);
		foreach(it, t; _selectedItems)
		{
			foreach(ip, p; t)
			{
				Color c = rgba(128, 128, 128, 128);

				if(it == 0 && ip == 0)
				{
					c = rgba(255, 0, 0, 128);
				}
				else if(_player2is == Player2is.FRIEND && it == 0 && ip == 1)
				{
					c = rgba(0, 255, 0, 128);
				}
				else if(_player2is == Player2is.ENEMY && it == 1 && ip == 0)
				{
					c = rgba(0, 255, 0, 128);
				}

				p.draw(teamColors[it], c);
			}
		}
	}


private:
	SelectedItem[2][2] _selectedItems;
	Player2is          _player2is;
	WallPaper          _wallPaper;
	OnQuit             _onQuit;
	int                _time;
}



private class WallPaper : Component
{
public:
	this(int stage)
	{
		if(stage == 0)
		{
			_progress = StaticMesh("$LIB/interval/1st.gsa");
		}
		else if(stage == 1)
		{
			_progress = StaticMesh("$LIB/interval/next.gsa");
		}
		else
		{
			_progress = StaticMesh("$LIB/interval/final.gsa");
		}

		_stage = StaticMesh("$LIB/interval/stage.gsa");
		_ball  = StaticMesh("$LIB/characterselect/ball.gsa");
	}


	override void onUpdate()
	{
		_time = (_time + 1) & 511;
	}


	override void onDraw()
	{
		GGL_clearScreen(0.0, 0.5, 1.0);

		auto t = _time & 127;
		auto s = false;
		for(float x=-512.0+t;x<512.0;x+=128.0)
		{
			for(float y=-512.0+t;y<512.0;y+=128.0)
			{
				if(s)
				{
					GGL_pushMatrix();

					GGL_translate(x, y, 0);

					GGL_rotate(.std.math.PI*2.0*t/128.0, 0, 0, 1);

					GGL_scale(16, 16, 1);

					_ball.draw(rgba(255, 255, 255, 64));

					GGL_popMatrix();
				}
				s = !s;
			}
			s = !s;
		}

		float y = -CANVAS_SIZE[1]*0.5 + CANVAS_SIZE[1]/8.0;

		Rect(0, y, CANVAS_SIZE[0], CANVAS_SIZE[1]/8.0).fill(rgba(0, 0, 0, 192));
		Rect(0, -y, CANVAS_SIZE[0], CANVAS_SIZE[1]/8.0).fill(rgba(0, 0, 0, 192));

		for(float x = _time - 512; x < 512; x += 512)
		{
			GGL_pushMatrix();

			GGL_translate(x, y, 0);

			GGL_scale(16, 16, 1);

			_progress.draw();
			_stage.draw();

			GGL_popMatrix();

			GGL_pushMatrix();

			GGL_translate(-x, -y, 0);

			GGL_scale(16, 16, 1);

			_progress.draw();
			_stage.draw();

			GGL_popMatrix();
		}
	}


private:
	StaticMesh _stage;
	StaticMesh _progress;
	StaticMesh _ball;
	int        _time;
}



private class SelectedItem
{
public:
	this(float x, float y, StaticMesh o, CharacterID id, int t, Sound se)
	{
		_position[0] = x;
		_position[1] = y;

		_operator    = o;

		_time = t + 16;

		_icon = createIcon(id);

		_se = se;
	}


	void update()
	{
		if(_time > 0)
		{
			--_time;
		}
	}


	void draw(Color c0, Color c1)
	{
		GGL_pushMatrix();

		if(_time > 0 && _time <= 16)
		{
			if(_time == 16)
			{
				Source().play(_se);
			}
			auto t = _time >> 1;

			if(t & 1)
			{
				GGL_translate(_position[0], _position[1] + t, 0);
			}
			else
			{
				GGL_translate(_position[0], _position[1] - t, 0);
			}
		}
		else
		{
			GGL_translate(_position[0], _position[1], 0);
		}

		Rect(0, 0, SELECTEDITEM_SIZE[0], SELECTEDITEM_SIZE[1]).fill(c0);

		GGL_pushMatrix();

		GGL_scale(SELECTEDITEM_SIZE[0]*0.5, SELECTEDITEM_SIZE[0]*0.5, 1.0);

		_operator.draw(c1);

		GGL_popMatrix();

		if(_time <= 16)
		{
			Rect(0, 0, SELECTEDITEM_SIZE[0], SELECTEDITEM_SIZE[1]).draw(_icon, WHITE);
		}

		GGL_popMatrix();
	}


private:
	StaticMesh _operator;
	float[2]   _position;
	Texture    _icon;
	Sound      _se;
	uint       _time;
}
