#pragma once

#include "stdafx.h"

typedef unsigned char TField[20][10];

//class CFigure
//{
//	class CRow
//	{
//	public:
//		CRow(unsigned short mask, unsigned int row): _mask(mask), _row(row) {}
//		bool operator [](unsigned int column) const throw()
//		{
//			_ASSERT(column < 4);
//			return _mask & 1u << column + _row * 4;
//		}
//	private:
//		const unsigned int _row;
//		const unsigned short _mask;
//	};
//public:
//	enum E_TYPE
//	{
//		T_QUAD,
//		T_PALKA,
//		T_G,
//		T_G_INV,
//		T_S,
//		T_S_INV,
//		T_TRI
//	};
//	enum E_ROTATE
//	{
//		R_0,
//		R_90,
//		R_180,
//		R_270
//	};
//	CFigure(E_TYPE type, E_ROTATE rotate, const TField &field);
//	int X() const throw() {return _x;}
//	int Y() const throw() {return _y;}
//	void MoveRight();
//	void MoveLeft();
//	bool MoveDown();
//	void Rotate(bool cw);
//	bool Collide() const;
//	CRow operator [](unsigned int row) const throw()
//	{
//		_ASSERT(row < 4);
//		return CRow(_masks[_maskIdx], row);
//	}
//	template<class F>
//	void Traverse(F callback) const throw(...);
//private:
//	enum E_MASK;
//	unsigned short GetFieldTileMask(int tileX, int tileY) const;
//	template<E_MASK mask> struct TMask;// map mask idx to mask
//	bool Collide(E_MASK mask) const;
//	enum E_MASK _maskIdx;
//	const TField &_field;
//	int _x, _y;
//	static const unsigned short _masks[];
//};
//
//class CTetris
//{
//	class CRow
//	{
//	public:
//		CRow(const TField &field, unsigned int row): _field(field), _row(row) {}
//		bool operator [](unsigned int column) const throw()
//		{
//			_ASSERT(column < 10);
//			return _field[_row / 4][column / 4] & 1u << column % 4 + _row % 4 * 4;
//		}
//	private:
//		const TField &_field;
//		const unsigned int _row;
//	};
//public:
//	CTetris() throw();
//	CRow operator [](unsigned int row) const throw()
//	{
//		_ASSERT(row < 20);
//		return CRow(_field, row);
//	}
//	template<class F>
//	void Traverse(F callback) const throw();
//	const CFigure &GetCurFigure() const throw()
//	{
//		return _curFigure;
//	}
//	void Process() throw();
//private:
//	TField _field;
//	CFigure _curFigure;
//	unsigned int _time;
//};

class CFigure
{
public:
	enum E_TYPE
	{
		T_QUAD,
		T_PALKA,
		T_G,
		T_G_INV,
		T_S,
		T_S_INV,
		T_TRI,
		T_LAST
	};
	enum E_ROTATE
	{
		R_0,
		R_90,
		R_180,
		R_270,
		R_LAST
	};
	CFigure(E_TYPE type, E_ROTATE rotate, unsigned char style, const TField &field);
	CFigure &operator =(const CFigure &src);
	int Row() const throw() {return _row;}
	int Column() const throw() {return _column;}
	void MoveRight();
	void MoveLeft();
	bool MoveDown();
	void Rotate(bool cw);
	bool Collide() const;
	template<bool relative, class F>
	void Traverse(F callback) const throw(...);
private:
	enum E_OFFSETS;
	bool Collide(E_OFFSETS offsetsIdx) const;
	enum E_OFFSETS _offsetsIdx;
	const TField &_field;
	int _row, _column;
	const unsigned char _style;
	static const unsigned char _offsets[][4][2];
};

class CTetris
{
public:
	enum E_EVENT
	{
		E_NONE,
		E_OVERFLOW,
		E_NEW_FIGURE
	};
	CTetris(unsigned char styleCount, unsigned int initialScore = 0) throw();
	operator const TField &() const throw()
	{
		return _field;
	}
	const unsigned char (&operator [](unsigned int row) const throw())[10]
	{
		_ASSERT(row < 20);
		return _field[row];
	}
	template<class F>
	void Traverse(F callback) const throw();
	const CFigure &GetCurFigure() const throw()
	{
		return _curFigure;
	}
	const CFigure &GetNextFigure() const throw()
	{
		return _nextFigure;
	}
	unsigned int Score() const throw()
	{
		return _score;
	}
	void MoveRight() throw() {_curFigure.MoveRight();}
	void MoveLeft() throw() {_curFigure.MoveLeft();}
	void Rotate(bool cw) throw() {_curFigure.Rotate(cw);}
	E_EVENT Process(bool boost) throw();
private:
	bool CheckRow(unsigned int row) const;
	TField _field;
	CFigure _curFigure, _nextFigure;
	unsigned int _time;
	unsigned int _score;
	float _delay;
	unsigned char _styleCount;
};