# include "BoardTestCase.h"
# include "TestHeader.h"
# include "Color.h"
# include "Square.h"
# include <Bitboard.h>
# include <Board.h>
# include "Pieces/Piece.h"
# include <Moves/SimpleMove.h>
# include <sstream>
using namespace Alice;
CPPUNIT_TEST_SUITE_REGISTRATION( BoardTestCase );
void 
BoardTestCase::construction()
{
  Board b;
};

void
BoardTestCase::at()
{
  Board b;
  Square sq(1,1);
  assert(b[sq]->isNull());
};

void
BoardTestCase::put()
{
  Board b;
  Square sq(1,1);
  Piece* k = Piece::newKing(Color::white());
  b.put( k, sq);
  assert(b[sq] == k);
  
};

void
BoardTestCase::forsythe()
{
  Board b;
  std::string s("k7/8/Q3q3/8/8/8/PPPPPPPP/8");
  std::istringstream in(s);
  assert(b.readForsythe(in));
  assert(b.at(Square(0,7))->isKing());
  std::ostringstream out;
  b.writeForsythe(out);
  assert(s == out.str());
};

void
BoardTestCase::testDisplay()
{
  Board b;
  b.initialPosition();
  std::ostringstream out;
  b.displayOn(out);
  std::string expected = 
    "  +---+---+---+---+---+---+---+---+\n"
    "8 |*R |*N |*B |*Q |*K |*B |*N |*R |\n"
    "  +---+---+---+---+---+---+---+---+\n"
    "7 |*P |*P |*P |*P |*P |*P |*P |*P |\n"
    "  +---+---+---+---+---+---+---+---+\n"
    "6 |   |   |   |   |   |   |   |   |\n"
    "  +---+---+---+---+---+---+---+---+\n"
    "5 |   |   |   |   |   |   |   |   |\n"
    "  +---+---+---+---+---+---+---+---+\n"
    "4 |   |   |   |   |   |   |   |   |\n"
    "  +---+---+---+---+---+---+---+---+\n"
    "3 |   |   |   |   |   |   |   |   |\n"
    "  +---+---+---+---+---+---+---+---+\n"
    "2 | P | P | P | P | P | P | P | P |\n"
    "  +---+---+---+---+---+---+---+---+\n"
    "1 | R | N | B | Q | K | B | N | R |\n"
    "  +---+---+---+---+---+---+---+---+\n"
    "    a   b   c   d   e   f   g   h\n";

  CPPUNIT_ASSERT_EQUAL(expected, out.str());
};

void
BoardTestCase::testBitboard()
{
  Board b;
  b.initialPosition();
  Bitboard expected1 = 0xc3c3c3c3c3c3c3c3ull;
  Bitboard result = b.getAllPieces();
  CPPUNIT_ASSERT_EQUAL( expected1, result );
  Square b1(1,0);
  Square c3(2,2);
  SmartPointer<Move> move = SimpleMove::createInstance(b1,c3);
  move->makeOn(b);
  Bitboard expected2 = 0xc3c3c3c3c3c7c2c3ull;
  result = b.getAllPieces();
  CPPUNIT_ASSERT_EQUAL( expected2, result );
  move->takeBackOn( b );
  result = b.getAllPieces();
  CPPUNIT_ASSERT_EQUAL( expected1, result );
};

void
BoardTestCase::testWhiteBitboard()
{
  Board b;
  b.initialPosition();
  Bitboard expected1 = 0x0303030303030303ull;
  Bitboard result = b.getWhitePieces();
  CPPUNIT_ASSERT_EQUAL( expected1, result );
};

void
BoardTestCase::testBlackBitboard()
{
  Board b;
  b.initialPosition();
  Bitboard expected1 = 0xc0c0c0c0c0c0c0c0ull;
  Bitboard result = b.getBlackPieces();
  CPPUNIT_ASSERT_EQUAL( expected1, result );
};

void
BoardTestCase::testRotatedBitboard()
{
  Board b;
  b.initialPosition();
  Bitboard expected = 0xffff00000000ffffull;
  Bitboard result = b.getAllPiecesRotated90();
  CPPUNIT_ASSERT_EQUAL( expected, result);
  b.clear( Square(7,0));
  Bitboard expected2 = 0xffff00000000ff7full;
  result = b.getAllPiecesRotated90();
  CPPUNIT_ASSERT_EQUAL( expected2, result );
};

void
BoardTestCase::testRotated45()
{
  Board b;
  b.initialPosition();
  Bitboard expected = 0xc3c3c3c3c3c3c3c3ull;
  Bitboard result = b.getAllPiecesRotated45();
  CPPUNIT_ASSERT_EQUAL( expected, result);
  b.clear( Square(7,0));
  expected.clearRotated45(Square(7,0));
  result = b.getAllPiecesRotated45();
  CPPUNIT_ASSERT_EQUAL( expected, result );
};

void
BoardTestCase::testTotalMaterial()
{
  Board b;
  b.initialPosition();
  CPPUNIT_ASSERT_EQUAL( 78, b.totalMaterial() );
  std::string forsythe = "k7/8/8/8/8/8/8/7K";
  std::istringstream stream(forsythe);
  b.readForsythe(stream);
  CPPUNIT_ASSERT_EQUAL( 0, b.totalMaterial());
};
