/*

	Ripatti Artem (c) 2012

	Тут куча реализаций преобразовательных блоков
	они все расширяют интерфейс XUnit

*/

#include "indirect_iface.h"

namespace indirect
{

	ZTriggerUnit::ZTriggerUnit()
	{
		_start_out = 0;
		_cur_out = 0;
		_block_inside = 0;
	}

	bool ZTriggerUnit::input_block( int x, int color )
	{
		if (x!=1) return false;
		_block_inside = color;
		return true;
	}

	int ZTriggerUnit::output_block( int x )
	{
		if (x != _cur_out*2) return 0;
		if (!_block_inside) return 0;
		int re = _block_inside;
		_cur_out = 1 - _cur_out;
		_block_inside = 0;
		return re;
	}

	void ZTriggerUnit::click()
	{
		_start_out = 1 - _start_out;
		_cur_out = 1 - _cur_out;
	}

	void ZTriggerUnit::reset()
	{
		_cur_out = _start_out;
		_block_inside = 0;
	}

	XUnit * ZTriggerUnit::get_copy()
	{
		ZTriggerUnit * re = new ZTriggerUnit();
		re->_cur_out = _cur_out;
		re->_block_inside = _block_inside;
		return re;
	}

	void ZTriggerUnit::draw( XGraphicEngine * GE, int x, int y, int mode, bool top )
	{
		GE->set_texture( indirect::TEXTURE_UNIT );
		float r=1.f, g=1.f, b=1.f;
		if (mode==1) { r=0.f; b=0.f; }
		else if (mode==2) { g=0.f; b=0.f; }
		else if (mode==3) { r=0.5f; g=0.5f; b=0.5f; }

		if (!top)
			GE->draw_pict( ge::PICT( (float)x, (float)y-8.f, 48.f, 32.f ).
				set_tex( 0.f, 0.f, 3.f/8.f, 1.f/4.f ).
				mul_to_color( r, g, b, 1.f ) );
		if (top)
		{
			GE->draw_pict( ge::PICT( (float)x, (float)y-12.f, 48.f, 32.f ).
				set_tex( 0.f, 0.25f, 3.f/8.f, 1.f/4.f ).
				mul_to_color( r, g, b, 1.f ) );
			if (!_cur_out)
				GE->draw_pict( ge::PICT( (float)x, (float)y-12.f, 16.f, 16.f ).
					set_tex( 3.f/8.f, 2.f/8.f, 1.f/8.f, 1.f/8.f ).
					mul_to_color( r, g, b, 1.f ) );
			else
				GE->draw_pict( ge::PICT( (float)x+32.f, (float)y-12.f, 16.f, 16.f ).
					set_tex( 3.f/8.f, 3.f/8.f, 1.f/8.f, 1.f/8.f ).
					mul_to_color( r, g, b, 1.f ) );
		}
	}

	string ZTriggerUnit::get_type()
	{
		return "z_trigger_unit";
	}

	string ZTriggerUnit::get_hint()
	{
		return "Trigger:\n"
		//	"1234567890123456\n"
			"Поочередно\n"
			"выводит блоки\n"
			"на левый и\n"
			"правый выходы.";
	}






	ZSwapperUnit::ZSwapperUnit()
	{
		_block1 = _block2 = 0;
	}

	bool ZSwapperUnit::input_block( int x, int color )
	{
		if (x==0)
			_block1 = color;
		else if (x==1) return false;
		else if (x==2)
			_block2 = color;
		return true;
	}

	int ZSwapperUnit::output_block( int x )
	{
		if (x == 0)
		{
			int re = _block2;
			_block2 = 0;
			return re;
		}
		else if (x == 1) return 0;
		else
		{
			int re = _block1;
			_block1 = 0;
			return re;
		}
	}

	void ZSwapperUnit::click()
	{

	}

	void ZSwapperUnit::reset()
	{
		_block1 = _block2 = 0;
	}

	XUnit * ZSwapperUnit::get_copy()
	{
		ZSwapperUnit * re = new ZSwapperUnit();
		re->_block1 = _block1;
		re->_block2 = _block2;
		return re;
	}

	void ZSwapperUnit::draw( XGraphicEngine * GE, int x, int y, int mode, bool top )
	{
		GE->set_texture( indirect::TEXTURE_UNIT );
		float r=1.f, g=1.f, b=1.f;
		if (mode==1) { r=0.f; b=0.f; }
		else if (mode==2) { g=0.f; b=0.f; }
		else if (mode==3) { r=0.5f; g=0.5f; b=0.5f; }

		if (!top)
			GE->draw_pict( ge::PICT( (float)x, (float)y-8.f, 48.f, 32.f ).
				set_tex( 0.f, 0.f, 3.f/8.f, 1.f/4.f ).
				mul_to_color( r, g, b, 1.f ) );
		if (top)
		{
			GE->draw_pict( ge::PICT( (float)x, (float)y-12.f, 48.f, 32.f ).
				set_tex( 0.f, 0.5f, 3.f/8.f, 1.f/4.f ).
				mul_to_color( r, g, b, 1.f ) );
		}
	}

	string ZSwapperUnit::get_type()
	{
		return "z_swapper_unit";
	}

	string ZSwapperUnit::get_hint()
	{
		return "Swapper:\n"
		//	"1234567890123456\n"
			"Перенаправляет\n"
			"блоки слева на\n"
			"правый выход и\n"
			"справа на левый.";
	}





	ZAccumulatorUnit::ZAccumulatorUnit()
	{
	}

	bool ZAccumulatorUnit::input_block( int x, int color )
	{
		if (x!=0) return false;
		_acc.push_back( color );
		return true;
	}

	int ZAccumulatorUnit::output_block( int x )
	{
		if ((int)_acc.size() == 3)
		{
			int re = _acc[2-x];
			if (x==2) _acc.clear();
			return re;
		}
		return 0;
	}

	void ZAccumulatorUnit::click()
	{

	}

	void ZAccumulatorUnit::reset()
	{
		_acc.clear();
	}

	XUnit * ZAccumulatorUnit::get_copy()
	{
		ZAccumulatorUnit * re = new ZAccumulatorUnit();
		re->_acc = _acc;
		return re;
	}

	void ZAccumulatorUnit::draw( XGraphicEngine * GE, int x, int y, int mode, bool top )
	{
		GE->set_texture( indirect::TEXTURE_UNIT );
		float r=1.f, g=1.f, b=1.f;
		if (mode==1) { r=0.f; b=0.f; }
		else if (mode==2) { g=0.f; b=0.f; }
		else if (mode==3) { r=0.5f; g=0.5f; b=0.5f; }

		if (!top)
			GE->draw_pict( ge::PICT( (float)x, (float)y-8.f, 48.f, 32.f ).
				set_tex( 0.f, 0.f, 3.f/8.f, 1.f/4.f ).
				mul_to_color( r, g, b, 1.f ) );
		if (top)
		{
			GE->draw_pict( ge::PICT( (float)x, (float)y-12.f, 48.f, 32.f ).
				set_tex( 0.f, 0.75f, 3.f/8.f, 1.f/4.f ).
				mul_to_color( r, g, b, 1.f ) );
			for (int a=0; a<3; a++)
				if ((int)_acc.size() > a)
					GE->draw_pict( ge::PICT( (float)x + (2-a)*16.f + 4.f, (float)y - 2.f, 8.f, 8.f ).
						set_tex( 3.f/8.f, 0.75f + _acc[a]/16.f, 1.f/16.f, 1.f/16.f ).
						mul_to_color( r, g, b, 1.f ) );
		}
	}

	string ZAccumulatorUnit::get_type()
	{
		return "z_accumulator_unit";
	}

	string ZAccumulatorUnit::get_hint()
	{
		return "Accumulator:\n"
		//	"1234567890123456\n"
			"Накапливает три\n"
			"блока, а затем\n"
			"одновременно\n"
			"выводит их.";
	}
};