# include "SquareTestCase.h"
# include "Square.h"
# include "TestHeader.h"
# include "Directions/Direction.h"
using namespace Alice;
CPPUNIT_TEST_SUITE_REGISTRATION( SquareTestCase );
void
SquareTestCase::testFile()
{
  for (int i = 0; i < 8; i++)
    for (int j = 0; j < 8; j++){
      Square sq(i, j);
      int file = sq.file();
      CPPUNIT_ASSERT(file == i);
    }
};
void
SquareTestCase::testRank()
{
  Square sq(3,4);
  int rank = sq.rank();
  CPPUNIT_ASSERT(rank == 4);
};

void
SquareTestCase::left()
{
  for (int i = 1; i < 8; i++)
    for (int j = 0; j < 8; j++) {
      Square sq(i, j);
      sq = sq.left();
      CPPUNIT_ASSERT_EQUAL( j, (int) sq.rank());
      CPPUNIT_ASSERT_EQUAL( (i-1), (int) sq.file());
      CPPUNIT_ASSERT(sq.isValid());
    }
  signed char i = 0;
  for (signed char j = 0; j < 8; j++) {
      Square sq(i, j);
			sq = sq.left();
      CPPUNIT_ASSERT(! sq.isValid());
  }
};
void
SquareTestCase::right()
{
  for (int i = 0; i < 7; i++)
    for (int j = 0; j < 8; j++) {
			Square sq(i, j);
			sq = sq.right();
      CPPUNIT_ASSERT_EQUAL( j,int(sq.rank()));
      CPPUNIT_ASSERT_EQUAL( i+1,int(sq.file()));
      CPPUNIT_ASSERT(sq.isValid());
    }
  int i = 7;
  for (int j = 0; j < 8; j++) {
      Square sq(i, j);
			sq = sq.right();
      CPPUNIT_ASSERT(! sq.isValid());
  }
};

void
SquareTestCase::up()
{
  for (int i = 0; i < 8; i++)
    for (int j = 0; j < 7; j++) {
    	Square sq(i, j);
    	sq = sq.up();
      CPPUNIT_ASSERT_EQUAL( j+1,int(sq.rank()));
      CPPUNIT_ASSERT_EQUAL( i,int(sq.file()));
      CPPUNIT_ASSERT(sq.isValid());
    }
  int j = 7;
  for (int i = 0; j < 8; j++) {
      Square sq(i, j);
    	sq = sq.up();
      CPPUNIT_ASSERT(! sq.isValid());
  }
};
void
SquareTestCase::down()
{
  for (signed char i = 0; i < 8; i++)
    for (signed char j = 1; j < 8; j++) {
      Square sq(i, j);
      sq = sq.down();
      CPPUNIT_ASSERT_EQUAL( j-1,int(sq.rank()));
      CPPUNIT_ASSERT_EQUAL( i,sq.file());
      CPPUNIT_ASSERT(sq.isValid());
    }
  int j = 0;
  for (int i = 0; i < 8; i++) {
      Square sq(i, j);
      sq = sq.down();
      CPPUNIT_ASSERT(! sq.isValid());
  }
};

void
SquareTestCase::directionUp()
{
	Direction::allInstances();
  for (int i = 0; i < 8; i++)
    for (int j = 0; j < 8; j++) {
      Square source(i,j);
      for (int k = 0; k < 8; k++)
	for (int l = 0; l < 8; l++){
	  Square destination(k, l);
	  const Direction* direction(&source.directionTo(destination));
	  CPPUNIT_ASSERT((direction &&direction->isUp()) == ((i == k) && (l > j)));
	  CPPUNIT_ASSERT((direction &&direction->isDown()) == ((i == k) && (l < j)));
	  CPPUNIT_ASSERT((direction &&direction->isLeft()) == ((i > k) && (l == j)));
	  CPPUNIT_ASSERT((direction &&direction->isRight()) == ((i < k) && (l == j)));
	  //delete direction;
	}
    }
};
void
SquareTestCase::knightDirections()
{
  for (int i = 0; i < 8; i++)
    for (int j = 0; j < 8; j++) {
      Square source(i,j);
      for (int k = 0; k < 8; k++)
	for (int l = 0; l < 8; l++){
	  Square destination(k, l);
	  int dx = k<i? i-k : k-i;
	  int dy = l<j ? j-l : l-j;
	  
	  const Direction* direction(&source.directionTo(destination));
	  CPPUNIT_ASSERT((direction->isKnightDirection()) == 
		 (dx == 1 && dy == 2 || dx == 2 && dy == 1));
	  //delete direction;
	}
    }
};
void
SquareTestCase::diagonalDirections()
{
  for (int i = 0; i < 8; i++)
    for (int j = 0; j < 8; j++) {
      Square source(i,j);
      for (int k = 0; k < 8; k++)
	for (int l = 0; l < 8; l++){
	  Square destination(k, l);
	  const Direction* direction(&source.directionTo(destination));
	  CPPUNIT_ASSERT((direction->isUpRight()) == (((i-k)==(j-l)) && (l > j)));
	  CPPUNIT_ASSERT((direction->isDownLeft()) == (((i-k)==(j-l)) && (l < j)));
	  CPPUNIT_ASSERT((direction->isUpLeft()) == (((i-k)==(l-j)) && (i > k)));
	  CPPUNIT_ASSERT((direction->isDownRight()) == (((i-k)==(l-j)) && (i < k)));
	  //delete direction;
	}
    }
};

void
SquareTestCase::allInstances()
{
  //Square::initializeAllInstances();
  CPPUNIT_ASSERT_EQUAL(size_t(64), Square::allInstances().size());
  Square::SquareIterator it = Square::allInstances().begin();
  for (int i= 0; i < 8; i++)
    for (int j = 0; j < 8; j++, it++)
      {
	CPPUNIT_ASSERT(i == it->file());
	CPPUNIT_ASSERT(j == it->rank());
      }
};


void
SquareTestCase::testNumber()
{
  int file = 3;
  int rank = 5;
  Square sq((file << Square::fileShift) + rank);
  CPPUNIT_ASSERT_EQUAL( file, (int)sq.file());
  CPPUNIT_ASSERT_EQUAL( rank, (int)sq.rank());
};

void
SquareTestCase::testDirections()
{
  Square sq(0,0);
  CPPUNIT_ASSERT( ! sq.down().isValid() );
  CPPUNIT_ASSERT( ! sq.left().isValid() );
  CPPUNIT_ASSERT( ! sq.down().right().isValid() );
  CPPUNIT_ASSERT( ! sq.down().left().isValid() );
  CPPUNIT_ASSERT( ! sq.up().left().isValid() );
};

void
SquareTestCase::testDownDiagonalNumber()
{
  Square sq(2,3);
  int result = sq.getDownDiagonalNumber();
  int expected = 5;
  CPPUNIT_ASSERT_EQUAL( expected, result );
};


void
SquareTestCase::testNumberRotated45()
{
  Square sq(0,0);
  int result = sq.getNumberRotated45();
  int expected = 0;
  CPPUNIT_ASSERT_EQUAL( expected, result );
  Square h2(7,1);
  result = h2.getNumberRotated45();
  CPPUNIT_ASSERT_EQUAL( 1, result);

  Square h8(7,7);
  CPPUNIT_ASSERT_EQUAL( 55, (int)h8.getNumberRotated45());
};

void
SquareTestCase::testNumberRotated135()
{
  Square sq(0,0);
  int result = sq.getNumberRotated135();
  int expected = 0;
  CPPUNIT_ASSERT_EQUAL( expected, result );
  Square a2(0,1);
  expected = 9;
  result = a2.getNumberRotated135();
  CPPUNIT_ASSERT_EQUAL( expected, result );
};

void
SquareTestCase::testUpDiagonalNumber()
{
  Square a1(0,0);
  int result = a1.getUpDiagonalNumber();
  int expected = 8;
  CPPUNIT_ASSERT_EQUAL( expected, result );
  Square a2(0,1);
  CPPUNIT_ASSERT_EQUAL(9, (int)a2.getUpDiagonalNumber());
  Square h1(7,0);
  CPPUNIT_ASSERT_EQUAL( 1, (int) h1.getUpDiagonalNumber());
};
