#ifndef INDIRECT_IFACE_H
#define INDIRECT_IFACE_H

/*
	Ripatti Artem (c) 2012

	объявления всех классов, нужных для игры INDIRECT
*/

#include "../core/ge_iface.h"
#include "../core/ie_iface.h"
#include "../core/se_iface.h"

#include <string>
#include <vector>
#include <set>
#include <map>

using namespace ge;
using namespace ie;
using namespace std;

namespace indirect
{

	enum ZRaceTextures
	{
		TEXTURE_SYSTEM		= 5,
		TEXTURE_LOGO		= 6,
		TEXTURE_IGDC		= 7,
		TEXTURE_FIELD		= 8,
		TEXTURE_BUTTON		= 9,
		TEXTURE_UNIT		= 10
	};

	struct ZBlock
	{
		int x, y, color;
		ZBlock( int _x=0, int _y=0, int _c=0 )
		{
			x = _x;
			y = _y;
			color = _c;
		}
	};

	class XUnit
	{
	public:
		virtual bool input_block( int x, int color ) = 0;
		virtual int output_block( int x ) = 0;
		virtual void click() = 0;
		virtual void reset() = 0;

		virtual XUnit * get_copy() = 0;

		virtual void draw( XGraphicEngine * GE, int x, int y, int mode, bool top ) = 0;

		virtual string get_type() = 0;
		virtual string get_hint() = 0;
	};

	class ZIndirectGame;

	class ZLevel
	{
		ZIndirectGame * _parent;

		int _field[11][11];
		string _in[11];
		string _out[11];
		int _done[11];

		int _num;
		int _diff;

		bool _run_mode;
		bool _crash_mode;
		bool _level_clear;
		bool _drag_unit_mode;
		bool _solved;

		int _drag_unit;

		string _crash_res;
		string _hint;

		vector< ZBlock > _vec;

		vector< XUnit * > _proto;
		vector< int > _count;

		int _kadr;

		map< XUnit *, pair< int, int > > _units;
		XUnit * unit_by_pos( int x, int y );
		bool can_place_unit( int x, int y );

		void run();
		void clear();
		void stop();
	public:
		ZLevel( ZIndirectGame * parent );
		//~ZLevel();

		void set_input( int x, string str );
		void set_output( int x, string str );
		void set_hint( string hint );
		void set_count( int c1, int c2, int c3, int c4, int c5, int c6 );
		void set_info( int num, int diff );

		int get_diff();
		bool is_solved();

		void do_input( XInputEngine * IE );
		void do_frame();
		void draw( XGraphicEngine * GE, XInputEngine * IE );
	};

	class ZIndirectGame
	{
		vector< ZLevel * > _levels;

		int _countdown;
		int _cur_level;
	public:
		ZIndirectGame();

		bool do_input( XInputEngine * IE );
		void draw( XGraphicEngine * GE, XInputEngine * IE );

		void leave_level();
	};

	class ZTriggerUnit : public XUnit
	{
		int _start_out, _cur_out;
		int _block_inside;
	public:
		ZTriggerUnit();

		virtual bool input_block( int x, int color );
		virtual int output_block( int x );
		virtual void click();
		virtual void reset();

		virtual XUnit * get_copy();

		virtual void draw( XGraphicEngine * GE, int x, int y, int mode, bool top );

		virtual string get_type();
		virtual string get_hint();
	};

	class ZSwapperUnit : public XUnit
	{
		int _block1, _block2;
	public:
		ZSwapperUnit();

		virtual bool input_block( int x, int color );
		virtual int output_block( int x );
		virtual void click();
		virtual void reset();

		virtual XUnit * get_copy();

		virtual void draw( XGraphicEngine * GE, int x, int y, int mode, bool top );

		virtual string get_type();
		virtual string get_hint();
	};

	class ZAccumulatorUnit : public XUnit
	{
		vector< int > _acc;
	public:
		ZAccumulatorUnit();

		virtual bool input_block( int x, int color );
		virtual int output_block( int x );
		virtual void click();
		virtual void reset();

		virtual XUnit * get_copy();

		virtual void draw( XGraphicEngine * GE, int x, int y, int mode, bool top );

		virtual string get_type();
		virtual string get_hint();
	};
}

#endif
