/*

	Ripatti Artem (c) 2012

	Тут главный класс игры
	Менюшка, состояние прохождения игры
	Тут же генерятся все уровни

*/

#include "indirect_iface.h"

#define TABLE_X		110
#define TABLE_Y		15

namespace indirect
{
	ZIndirectGame::ZIndirectGame()
	{
		_cur_level = -1;
		_countdown = 240;

		ZLevel * lvl = 0;

		lvl = new ZLevel( this );
		lvl->set_input( 5, "ABC" );
		lvl->set_output( 5, "ABC" );
		lvl->set_hint(
		//	"1234567890123456\n"
			"Используйте\n"
			"конвееры чтобы\n"
			"переместить\n"
			"цветные блоки\n"
			"сверху вниз.");
		lvl->set_count( -1, -1, -1, -1, -1, -1 );
		lvl->set_info( 1, 1 );
		_levels.push_back( lvl );

		lvl = new ZLevel( this );
		lvl->set_input( 3, "AC" );
		lvl->set_input( 7, "BC" );
		lvl->set_output( 5, "ACBC" );
		lvl->set_hint(
		//	"1234567890123456\n"
			"Осторожно,\n"
			"цветные блоки\n"
			"не должны\n"
			"сталкиваться\n"
			"друг с другом.");
		lvl->set_count( -1, -1, -1, -1, -1, -1 );
		lvl->set_info( 2, 1 );
		_levels.push_back( lvl );

		lvl = new ZLevel( this );
		lvl->set_input( 5, "AB" );
		lvl->set_output( 5, "BA" );
		lvl->set_hint(
		//	"1234567890123456\n"
			"Перетаскивайте\n"
			"исполнительные\n"
			"блоки из панели\n"
			"справа на поле\n"
			"с помощью мыши.");
		lvl->set_count( 1, -1, -1, -1, -1, -1 );
		lvl->set_info( 3, 1 );
		_levels.push_back( lvl );

		lvl = new ZLevel( this );
		lvl->set_input( 3, "AA" );
		lvl->set_input( 7, "BB" );
		lvl->set_output( 3, "BB" );
		lvl->set_output( 7, "AA" );
		lvl->set_hint(
		//	"1234567890123456\n"
			"Щелкните на\n"
			"исполнительном\n"
			"блоке чтобы\n"
			"изменить его\n"
			"состояние.");
		lvl->set_count( 2, -1, -1, -1, -1, -1 );
		lvl->set_info( 4, 2 );
		_levels.push_back( lvl );

		lvl = new ZLevel( this );
		lvl->set_input( 3, "ABB" );
		lvl->set_input( 7, "ACC" );
		lvl->set_output( 5, "ABABCC" );
		lvl->set_hint(
		//	"1234567890123456\n"
			"В этой игре\n"
			"классная музыка.\n"
			"Не правда ли?");
		lvl->set_count( 2, -1, -1, -1, -1, -1 );
		lvl->set_info( 5, 2 );
		_levels.push_back( lvl );

		lvl = new ZLevel( this );
		lvl->set_input( 2, "AAA" );
		lvl->set_input( 5, "BBB" );
		lvl->set_input( 8, "CCC" );
		lvl->set_output( 2, "ABC" );
		lvl->set_output( 5, "ABC" );
		lvl->set_output( 8, "ABC" );
		lvl->set_hint(
		//	"1234567890123456\n"
			"Просто сложный\n"
			"уровень. Ничего\n"
			"особенного.");
		lvl->set_count( 3, -1, -1, -1, -1, -1 );
		lvl->set_info( 6, 3 );
		_levels.push_back( lvl );

		lvl = new ZLevel( this );
		lvl->set_input( 2, "CA" );
		lvl->set_input( 5, "BC" );
		lvl->set_input( 8, "AB" );
		lvl->set_output( 2, "BB" );
		lvl->set_output( 5, "AA" );
		lvl->set_output( 8, "CC" );
		lvl->set_hint(
		//	"1234567890123456\n"
			"Этот уровень\n"
			"действительно\n"
			"сложный. К нему\n"
			"всегда можно\n"
			"вернуться потом.");
		lvl->set_count( 6, -1, -1, -1, -1, -1 );
		lvl->set_info( 7, 3 );
		_levels.push_back( lvl );

		lvl = new ZLevel( this );
		lvl->set_input( 2, "AAA" );
		lvl->set_input( 5, "BBB" );
		lvl->set_input( 8, "CCC" );
		lvl->set_output( 2, "CCC" );
		lvl->set_output( 5, "BBB" );
		lvl->set_output( 8, "AAA" );
		lvl->set_hint(
		//	"1234567890123456\n"
			"Ознакомьтесь\n"
			"с новым видом\n"
			"исполнительных\n"
			"блоков.");
		lvl->set_count( -1, 3, -1, -1, -1, -1 );
		lvl->set_info( 8, 1 );
		_levels.push_back( lvl );

		lvl = new ZLevel( this );
		lvl->set_input( 2, "ABA" );
		lvl->set_input( 5, "ACA" );
		lvl->set_input( 8, "CAB" );
		lvl->set_output( 2, "AAAAA" );
		lvl->set_output( 5, "CC" );
		lvl->set_output( 8, "BB" );
		lvl->set_hint(
		//	"1234567890123456\n"
			"Не обязательно\n"
			"использовать все\n"
			"управляющие\n"
			"блоки чтобы\n"
			"пройти уровень.");
		lvl->set_count( 2, 2, -1, -1, -1, -1 );
		lvl->set_info( 9, 2 );
		_levels.push_back( lvl );

		lvl = new ZLevel( this );
		lvl->set_input( 0, "A" );
		lvl->set_input( 1, "B" );
		lvl->set_input( 2, "C" );
		lvl->set_input( 3, "A" );
		lvl->set_input( 4, "B" );
		lvl->set_input( 5, "C" );
		lvl->set_input( 6, "A" );
		lvl->set_input( 7, "B" );
		lvl->set_input( 8, "C" );
		lvl->set_input( 9, "A" );
		lvl->set_input( 10, "B" );
		lvl->set_output( 2, "AAAA" );
		lvl->set_output( 5, "BBBB" );
		lvl->set_output( 8, "CCC" );
		lvl->set_hint(
		//	"1234567890123456\n"
			"Очень много\n"
			"цветных блоков.\n"
			"И все по одному.");
		lvl->set_count( 1, 3, -1, -1, -1, -1 );
		lvl->set_info( 10, 2 );
		_levels.push_back( lvl );

		lvl = new ZLevel( this );
		lvl->set_input( 2, "AAA" );
		lvl->set_input( 5, "BBB" );
		lvl->set_input( 8, "CCC" );
		lvl->set_output( 2, "ABC" );
		lvl->set_output( 5, "ABC" );
		lvl->set_output( 8, "ABC" );
		lvl->set_hint(
		//	"1234567890123456\n"
			"Еще один новый\n"
			"управляющий\n"
			"блок. Изучите\n"
			"принцип его\n"
			"работы.");
		lvl->set_count( -1, -1, 1, -1, -1, -1 );
		lvl->set_info( 11, 1 );
		_levels.push_back( lvl );

		lvl = new ZLevel( this );
		lvl->set_input( 2, "BBA" );
		lvl->set_input( 4, "CA" );
		lvl->set_input( 6, "AB" );
		lvl->set_input( 8, "C" );
		lvl->set_output( 2, "CC" );
		lvl->set_output( 5, "BBB" );
		lvl->set_output( 8, "AAA" );
		lvl->set_hint(
		//	"1234567890123456\n"
			"Здесь могла\n"
			"быть ваша\n"
			"реклама.");
		lvl->set_count( 1, -1, 1, -1, -1, -1 );
		lvl->set_info( 12, 2 );
		_levels.push_back( lvl );

		lvl = new ZLevel( this );
		lvl->set_input( 1, "A" );
		lvl->set_input( 3, "C" );
		lvl->set_input( 5, "B" );
		lvl->set_input( 7, "B" );
		lvl->set_input( 9, "B" );
		lvl->set_output( 2, "BBB" );
		lvl->set_output( 8, "AC" );
		lvl->set_hint(
		//	"1234567890123456\n"
			"Это последний\n"
			"уровень в данной\n"
			"версии игры.\n"
			"Ждите полную\n"
			"версию ;)");
		lvl->set_count( -1, -1, 3, -1, -1, -1 );
		lvl->set_info( 13, 2 );
		_levels.push_back( lvl );

	}

	bool ZIndirectGame::do_input( XInputEngine * IE )
	{
		if (_countdown) return true;

		if (_cur_level != -1)
		{
			_levels[_cur_level]->do_input( IE );
			if (_cur_level==-1) return true;
			_levels[_cur_level]->do_frame();
			return true;
		}

		int x = IE->get_mouse_x()/2, y = IE->get_mouse_y()/2;
		for (int a=0; a<(int)_levels.size(); a++)
		{
			int xx = TABLE_X + (a%5)*40, yy = TABLE_Y + (a/5)*40;
			if (xx<=x && x<xx+40 && yy<=y && y<yy+40)
				if (IE->mouse_pressed( 0, false, true ))
				{
					_cur_level = a;
					return true;
				}
		}

		return true;
	}

	void ZIndirectGame::draw( XGraphicEngine * GE, XInputEngine * IE )
	{
		if (_countdown)
		{
			if (120 < _countdown && _countdown <= 240)
			{
				float alpha = std::min(std::min(240 - _countdown, _countdown - 120), 30)/30.f;
				GE->set_texture( indirect::TEXTURE_LOGO );
				GE->draw_pict( ge::PICT( 160.f-50.f, 120.f-50.f, 100.f, 100.f ).
					mul_to_color( 1.f, 1.f, 1.f, alpha ) );
			}
			
			if (0 < _countdown && _countdown <= 120)
			{
				float alpha = std::min(std::min(120 - _countdown, _countdown), 30)/30.f;
				GE->set_texture( indirect::TEXTURE_IGDC );
				GE->draw_pict( ge::PICT( 160.f-100.f, 120.f-100.f, 200.f, 200.f ).
					mul_to_color( 1.f, 1.f, 1.f, alpha ) );
			}
			
			_countdown--;
			return;
		}

		if (_cur_level != -1)
		{
			_levels[_cur_level]->draw( GE, IE );
			return;
		}

		GE->write( 50, 15, "Great\nPermutator\nv0.9", 1.f, 1.f, 1.f );
		GE->write( 50, 60, "специально\nдля igdc.ru", 0.5f, 0.7f, 0.5f );
		GE->write( 50, 90, "rip -\nидея, арт,\nпрограмминг", 0.5f, 0.5f, 0.7f );
		GE->write( 50, 140, "Taniuchi\nHideki -\nмузыка\n(Akagi OST)", 0.7f, 0.5f, 0.5f );
		GE->write( 50, 200, "Enjoy!", 0.9f, 0.9f, 0.5f );

		GE->write( 160, 220, "Ripatti Software (c) 2012", 0.3f, 0.3f, 0.3f );

		GE->set_texture( indirect::TEXTURE_BUTTON );
		for (int a=0; a<(int)_levels.size(); a++)
		{
			GE->draw_pict( ge::PICT( (float)TABLE_X + (a%5)*40.f, (float)TABLE_Y + (a/5)*40.f, 40.f, 40.f ).
				set_tex( 0.f, 0.25f, 0.5f, 0.5f ) );
			char ch[20];
			sprintf_s( ch, "LVL%d", a+1 );
			GE->write( (float)TABLE_X + (a%5)*40.f + 20.f, (float)TABLE_Y + (a/5)*40.f + 1.f, ch, 1.f, 1.f, 1.f, 1.f );
			GE->draw_pict( ge::PICT( (float)TABLE_X + (a%5)*40.f, (float)TABLE_Y + (a/5)*40.f + 15.f, 40.f, 10.f ).
				set_tex( 0.5f, 0.25f + (float)(_levels[a]->get_diff()-1)/8.f, 0.5f, 0.125f ) );
			if (_levels[a]->is_solved())
				GE->draw_pict( ge::PICT( (float)TABLE_X + (a%5)*40.f, (float)TABLE_Y + (a/5)*40.f + 27.f, 40.f, 10.f ).
					set_tex( 0.5f, 5.f/8.f, 0.5f, 0.125f ) );
		}
	}

	void ZIndirectGame::leave_level()
	{
		_cur_level = -1;
	}
};