#include <list>
#include <vector>
#include <time.h>

using namespace std;

#define NORMAL 0
#define RIGHT_BORDER 1
#define BOTTOM_BORDER 2
#define UP_OR_LEFT_BORDER 3
#define CORNER 4


struct RotPieces
{
	int top;
	int right;
	int bottom;
	int left;
	bool*  isUsed;
};

struct Piece
{
	int* top;
	int* right;
	int* bottom;
	int* left;
	int type;
};

class EternityIISolver
{

public:

EternityIISolver();

~EternityIISolver();

void solve();

void subSolve(int piecesRestantes);

void readPieces();



inline void printSolution()
{
	int nbPoints = (_sizeX+1)*(_sizeY) + (_sizeX)*(_sizeY+1) ;
    int i=0;
	int j=0;	

		int nbPoints2Lignes = 1+2*_sizeY;
		int nbPointsAffiches = 0 ;
		fprintf(_Solutions,"\n");
		while(nbPointsAffiches<nbPoints)
		{
			
			fprintf(_Solutions,"\n");
			fprintf(_Solutions,"  ");
			for(i=0;i<_sizeY;i++)
			{  
				fprintf(_Solutions," |");
				if (_valueSolution[i+nbPointsAffiches]<10) fprintf(_Solutions,"0");
				fprintf(_Solutions,"%i| ",_valueSolution[i+nbPointsAffiches]);			
			}	
			fprintf(_Solutions,"\n");
			nbPointsAffiches+=_sizeY;
			if (nbPointsAffiches>=nbPoints) break;
			for(i=0;i<_sizeY+1;i++)
			{			
				fprintf(_Solutions,"|");
				if (_valueSolution[i+nbPointsAffiches]<10) fprintf(_Solutions,"0");
				fprintf(_Solutions,"%i|  ",_valueSolution[i+nbPointsAffiches]);			
			}	
			nbPointsAffiches+=_sizeY+1;
		}
		
}


inline void printnbSolutions()
{
	fprintf(_Solutions,"\n nbSolutions : %i\n",_nbSolutions);
}


inline void printStats()
{
	int temps_cpu = (clock () - temps_initial) / CLOCKS_PER_SEC * 1000; // millisecondes
	printf("\nTemps d'execution : %i\n", temps_cpu );
	printf("\n Nb de Pièces posées : %llu\n", _nbPiecesPoser );
	printf("\n Nb de Millions de Pièces par seconde : %f\n", (float)_nbPiecesPoser/(temps_cpu*1000) );
}


int _sizeX;
int _sizeY;

__int64 _nbPiecesPoser;

vector<RotPieces*>*** _PiecesByValue;
vector<RotPieces*>*** _BorderPiecesByValue;
vector<RotPieces*>*** _RightBorderPiecesByValue;
vector<RotPieces*>*** _BottomBorderPiecesByValue;
vector<RotPieces*>*** _CornerPiecesByValue;

FILE* _Solutions;

int* _valueSolution;

int _nbSolutions;

Piece** _pointeurSolutions;
Piece** _iterPointeurSolutions;

char* filename;

double temps_initial;	

};
