# include "MoveTestCase.h"
# include "TestHeader.h"
# include "Color.h"
# include "Square.h"
# include "Pieces/Piece.h"
# include "Board.h"
# include "Moves/SimpleMove.h"
# include "Moves/CapturingMove.h"
# include "Moves/PromotingMove.h"
# include "Moves/PromotingCapture.h"
# include <Pieces/Queen.h>
# include <Pieces/Rook.h>
# include "Moves/CastlingMove.h"
# include <sstream>
# include <Bitboard.h>
# include <Game/Game.h>
using namespace Alice;
CPPUNIT_TEST_SUITE_REGISTRATION(MoveTestCase);
void
MoveTestCase::simpleMove()
{
  Board b;
  std::string before("8/8/8/8/8/8/8/K7");
  Square a1(0,0);
  Square b1(1,0);
  SmartPointer<Move> move = SimpleMove::createInstance(a1, b1);
  std::string after("8/8/8/8/8/8/8/1K6");
  
  doTest(before, after, *move);

};


void
MoveTestCase::promotingMove()
{
  std::string before("8/P7/8/8/8/8/8/8");
  Square a7(0,6);
  Square a8(0,7);
  {
    PromotingMove move(a7, a8, Piece::newQueen(Color::white()));
    std::string after("Q7/8/8/8/8/8/8/8");
    doTest(before, after, move);
  }
  {
    PromotingMove move(a7, a8, Piece::newRook(Color::white()));
    std::string after("R7/8/8/8/8/8/8/8");
    doTest(before, after, move);
  }
};
void
MoveTestCase::promotingCapture()
{
  std::string before("2q5/1P6/8/8/8/8/8/8");
  
  Square b7(1,6);
  Square c8(2,7);
  PromotingCapture move(b7, c8, Piece::newRook(Color::white()));
  std::string after("2R5/8/8/8/8/8/8/8");
  
  doTest(before, after, move);
};

void
MoveTestCase::castlingMove()
{
  std::string before("r3k2r/8/8/8/8/8/8/R3K2R");
  
  Square e1(4,0);
  Square f1(5,0);
  Square g1(6,0);
  Square h1(7,0);
  CastlingMove move(e1, g1, h1, f1);
  std::string after("r3k2r/8/8/8/8/8/8/R4RK1");
  
  doTest(before, after, move);
};
void 
MoveTestCase::doTest(const std::string& before, const std::string& after,
	      Move& move)
{
  Board b;
  std::istringstream in(before);
  b.readForsythe(in);
  Bitboard whitePieces = b.getWhitePieces();
  Bitboard blackPieces = b.getBlackPieces();
  move.makeOn(b);
  {
    std::ostringstream out;
    b.writeForsythe(out);
    if (after != out.str())
      std::cout<<std::endl<<after<<std::endl<<out.str()<<std::endl;
    CPPUNIT_ASSERT_EQUAL(after, out.str());
  }
  move.takeBackOn(b);
  {
    std::ostringstream out;
    b.writeForsythe(out);
    CPPUNIT_ASSERT_EQUAL(before, out.str());
  }
  CPPUNIT_ASSERT_EQUAL( whitePieces, b.getWhitePieces());
  CPPUNIT_ASSERT_EQUAL( blackPieces, b.getBlackPieces());
};

void
MoveTestCase::equality()
{
  Square a1(0,0);
  Square a2(0,1);
  //  Square a3(0,2);
  SmartPointer<Move> a1a2 = SimpleMove::createInstance(a1, a2);
  CPPUNIT_ASSERT(*a1a2 == *a1a2);
  CapturingMove* a1xa2 = new CapturingMove(a1, a2);
  CPPUNIT_ASSERT(*a1a2 == *a1xa2);
  PromotingMove* a2a1q = new PromotingMove(a2, a1, new Queen(Color::black()));
  CPPUNIT_ASSERT(*a1a2 != *a2a1q);
  PromotingMove* a2a1r = new PromotingMove(a2, a1, new Rook(Color::black()));
  CPPUNIT_ASSERT(*a2a1q == *a2a1q);
  CPPUNIT_ASSERT(*a2a1q != *a2a1r);
};

void
MoveTestCase::testIsLegal()
{
  //  CPPUNIT_FAIL( "not implemented" );

  Square a7(0,6);
  Square b8(1,7);
  PromotingCapture move(a7,b8, new Rook(Color::white()));
  Game g;
  g.forsytheString("8/P6k/K7/8/8/8/8/8");
  CPPUNIT_ASSERT( !move.isLegal(g) );
};
