module vs.scene.title;



private import gedo.audio.music;
private import gedo.audio.sound;
private import gedo.video.ggl;
private import gedo.video.texture;
private import gedo.gui.label;
private import gedo.gui.table;
private import gedo.gui.camera;
private import gedo.gui.cursor;
private import gedo.gui.component;
private import gedo.input.joystick;
private import gedo.system.scene;
private import gedo.system.gameloop;
private import gedo.file.config;
private import vs.scene.config;



alias Scene delegate(Title title) OnQuit;



public class Title : Scene
{
public:
	enum Result
	{
		TOURNAMENT_SOLO,
		TOURNAMENT_FRIEND_2P,
		VS_SOLO,
		VS_FRIEND_2P,
		VS_ENEMY_2P,
		TIMEOUT,
	}


	this(OnQuit dg)
	{
		_onQuit = dg;

		_time = 0;

		_bg        = new ImageLabel(Texture("$LIB/title/bg.png", false));
		_logo      = new ImageLabel(Texture("$LIB/title/logo.png", false));
		_logo.position[1] = 240.0 - _logo.texture.height*0.5;
		_pushStart = new ImageLabel(Texture("$LIB/title/pushstart.png", false));
		_pushStart.position[1] = -120.0;

		auto camera = new Camera(640, 480, 0.0, 0.5, 1.0);

		camera.add(_bg);

		createCursor();

		_bgm = new Music("$LIB/title/bgm.txt");

		_bgm.play();
	}


	override void update()
	{
		++_time;
		switch(_time)
		{
		case 1:
			_bg.slideIn();
			break;

		case 33:
			_bg.add(_logo);
			_logo.vibrate();
			break;

		case 65:
			if(!_cursor.joystick)
			{
				_logo.add(_pushStart);
				_pushStart.blink();
			}
			break;

		case 512:
			if(!_cursor.joystick)
			{
				_result = Result.TIMEOUT;

				_nextScene = _onQuit(this);
			}
			break;

		default:
			break;
		}

		_bg.root.update();

		if(!_cursor.joystick)
		{
			_cursor.joystick = Joysticks().detectPressed();
			if(_cursor.joystick)
			{
				auto sound = Sound("$LIB/cursor_click.ogg");
				Source().play(sound);
				if(_pushStart.parent)
				{
					_logo.remove(_pushStart);
				}
			}
		}
		else
		{
			_cursor.focus.root.update();

			_cursor.update();
		}
	}


	override void draw()
	{
		_bg.root.drawRecursive();

		if(_cursor.joystick)
		{
			if(_cursor.focus.parent)
			{
				_cursor.focus.parent.draw();
				foreach(item; _cursor.focus.parent)
				{
					item.draw();
				}
			}
			else
			{
				_cursor.focus.draw();
			}

			_cursor.draw();
		}
	}


	uint cplevel()
	{
		auto config = GameLoop().config;

		return config.get("cp.level", 0);
	}


	uint arrowSize()
	{
		auto config = GameLoop().config;

		return config.get("arrow.size", 100);
	}


	bool isHitCameraEnable()
	{
		auto config = GameLoop().config;

		return config.get("hitcamera", true);
	}


	float bgmVolume()
	{
		return GameLoop().config.get("volume.bgm", 0.75);
	}


	float seVolume()
	{
		return GameLoop().config.get("volume.se", 0.75);
	}


	Joystick joystick1()
	{
		return _cursor.joystick;
	}


	Joystick joystick2()
	{
		return _joystick2;
	}


	Result result()
	{
		return _result;
	}


private:
	ImageLabel _bg;
	ImageLabel _logo;
	ImageLabel _pushStart;
	Joystick   _joystick2;
	Cursor     _cursor;
	Result     _result;
	OnQuit     _onQuit;
	Music      _bgm;
	uint       _time;


	void createCursor()
	{
		_cursor = new .gedo.gui.cursor.Cursor();
		_cursor.joystick = null;

		auto rootMenu = new Component();

		auto table = new Table(1, 4);

		rootMenu.add(table);
		_cursor.focus = table.rows[0];

		auto item = new ImageLabel(Texture("$LIB/title/tournament.png", false));
		table.set(0, 0, item);
		{
			auto subtable = new Table(1, 2);

			auto subitem = new ImageLabel(Texture("$LIB/title/solo.png", false));
			subtable.set(0, 0, subitem);
			subtable.rows[0].cbClick = &onClickTournamentSolo;

			subitem = new ImageLabel(Texture("$LIB/title/friend2p.png", false));
			subtable.set(0, 1, subitem);
			subtable.rows[1].cbClick = &onClickTournamentFriend;

			table.rows[0].add(subtable);
		}

		item = new ImageLabel(Texture("$LIB/title/vs.png", false));
		table.set(0, 1, item);
		{
			auto subtable = new Table(1, 3);

			auto subitem = new ImageLabel(Texture("$LIB/title/solo.png", false));
			subtable.set(0, 0, subitem);
			subtable.rows[0].cbClick = &onClickVSSolo;

			subitem = new ImageLabel(Texture("$LIB/title/friend2p.png", false));
			subtable.set(0, 1, subitem);
			subtable.rows[1].cbClick = &onClickVSFriend;

			subitem = new ImageLabel(Texture("$LIB/title/enemy2p.png", false));
			subtable.set(0, 2, subitem);
			subtable.rows[2].cbClick = &onClickVSEnemy;

			table.rows[1].add(subtable);
		}

		item = new ImageLabel(Texture("$LIB/title/config.png", false));
		table.set(0, 2, item);
		table.rows[2].cbClick = &onClickConfig;

		item = new ImageLabel(Texture("$LIB/title/quit.png", false));
		table.set(0, 3, item);
		table.rows[3].cbClick = &onClickQuit;

		table.update();
		table.position[0] = 0.0;
		table.position[1] = -240.0 + 16.0 + table.size[1]*0.5;
	}


	void onClickTournamentSolo()
	{
		_result = Result.TOURNAMENT_SOLO;

		_nextScene = _onQuit(this);
	}


	void onClickTournamentFriend()
	{
		detect2PJoystick(&enterTournamentFriend);
	}


	void onClickVSSolo()
	{
		_result = Result.VS_SOLO;

		_nextScene = _onQuit(this);
	}


	void onClickVSFriend()
	{
		detect2PJoystick(&enterVSFriend);
	}


	void onClickVSEnemy()
	{
		detect2PJoystick(&enterVSEnemy);
	}


	void onClickConfig()
	{
		_nextScene = new ConfigScene(this, _bg.root, _cursor.joystick, &onQuitConfig, cplevel, arrowSize, isHitCameraEnable, bgmVolume, seVolume);
	}


	void onClickQuit()
	{
		GameLoop().quit();
	}


	void detect2PJoystick(OnJoystickFound dg)
	{
		if(Joysticks().items.length < 2)
		{
			new NoPadError(_cursor);
		}
		else
		{
			_cursor.focus = new PushButton(_cursor, dg);
		}
	}


	void enterTournamentFriend(Joystick pad)
	{
		_result = Result.TOURNAMENT_FRIEND_2P;

		_joystick2 = pad;

		_nextScene = _onQuit(this);
	}


	void enterVSFriend(Joystick pad)
	{
		_result = Result.VS_FRIEND_2P;

		_joystick2 = pad;

		_nextScene = _onQuit(this);
	}


	void enterVSEnemy(Joystick pad)
	{
		_result = Result.VS_ENEMY_2P;

		_joystick2 = pad;

		_nextScene = _onQuit(this);
	}


	void onQuitConfig(ConfigScene scene)
	{
		GameLoop().config.set("cp.level", cast(int)scene.cplevel);
		GameLoop().config.set("arrow.size", cast(int)scene.arrowSize);
		GameLoop().config.set("hitcamera", scene.isHitCameraEnable);
		GameLoop().config.set("volume.bgm", scene.bgmVolume);
		GameLoop().config.set("volume.se", scene.seVolume);
	}
}



alias void delegate(Joystick) OnJoystickFound;



private class PushButton : ImageLabel
{
public:
	this(gedo.gui.cursor.Cursor cursor, OnJoystickFound dg)
	{
		super(Texture("$LIB/title/pushbutton2p.png", false));

		position[] = 0.0;

		slideIn();

		_cursor = cursor;
		_dg     = dg;
	}


	override void onUpdate()
	{
		super.onUpdate();

		if(!isAnimating())
		{
			if(auto pad2p = Joysticks().detectPressed())
			{
				if(pad2p !is _cursor.joystick)
				{
					_dg(pad2p);
				}
			}
		}
	}


private:
	gedo.gui.cursor.Cursor _cursor;
	OnJoystickFound        _dg;
}



private class NoPadError : ImageLabel
{
public:
	this(gedo.gui.cursor.Cursor cursor)
	{
		super(Texture("$LIB/title/nopad2p.png", false));

		position[] = 0.0;

		slideIn();

		_focus = cursor.focus;

		cursor.focus = this;

		_cursor = cursor;
	}


	override void onUpdate()
	{
		super.onUpdate();

		if(!isAnimating())
		{
			if(position[0] < -320.0)
			{
				_cursor.focus = _focus;
			}
			else if(_cursor.joystick.buttons[0].isPushed(0))
			{
				slideOut();
			}
		}
	}


private:
	gedo.gui.cursor.Cursor _cursor;
	Component              _focus;
}
