# include "CheckSentryTestCase.h"
# include "Game/CheckSentry.h"
# include "Game/Game.h"
# include "TestHeader.h"
# include "Color.h"
# include "Square.h"
# include "Pieces/Piece.h"
# include "Moves/SimpleMove.h"
# include "Moves/CastlingMove.h"
# include "Moves/DoubleStep.h"
# include "Moves/EnPassantMove.h"
# include "Directions/Direction.h"
# include <sstream>
using namespace Alice;
void
CheckSentryTestCase::findKings()
{
  Game g;
  g.forsytheString("4k3/8/8/8/8/8/8/4K3/");
  CheckSentry cs;
  cs.startObserving(&g);
  Square e1(4, 0);
  Square whiteKing = cs.findKing(Color::white());
  CPPUNIT_ASSERT(whiteKing == e1);
  Square e8(4, 7);
  Square blackKing = cs.findKing(Color::black());
  CPPUNIT_ASSERT(blackKing == e8);
  Square e2(4, 1);
  SmartPointer<Move> move = SimpleMove::createInstance(e1, e2);
  move->makeOn(g);
  whiteKing = cs.findKing(Color::white());
  CPPUNIT_ASSERT(whiteKing == e2);
  move->takeBackOn(g);
  whiteKing = cs.findKing(Color::white());
  CPPUNIT_ASSERT(whiteKing == e1);
};

void
CheckSentryTestCase::simpleChecks()
{
  Game g;
  g.forsytheString("k7/8/8/8/Q6r/8/8/7K/");
  CheckSentry cs;
  cs.startObserving(&g);
  CPPUNIT_ASSERT(cs.isInCheck(Color::white()));
  CPPUNIT_ASSERT(cs.isInCheck(Color::black()));
};

void
CheckSentryTestCase::queenChecks()
{
  Game g;
  g.forsytheString("k7/8/8/8/8/8/8/1QK5/");
  CheckSentry cs;
  cs.startObserving(&g);
  CPPUNIT_ASSERT(cs.isInCheck(Color::white()) == false);
  CPPUNIT_ASSERT(cs.isInCheck(Color::black()) == false);
  Square a1(0,0);
  Square b1(1,0);
  SmartPointer<Move> move = SimpleMove::createInstance(b1, a1);
  move->makeOn(g);
  CPPUNIT_ASSERT(cs.isInCheck(Color::white()) == false);
  CPPUNIT_ASSERT(cs.isInCheck(Color::black()) == true);
  move->takeBackOn(g);
  CPPUNIT_ASSERT(cs.isInCheck(Color::white()) == false);
  CPPUNIT_ASSERT(cs.isInCheck(Color::black()) == false);
  
};
void
CheckSentryTestCase::rookChecks()
{
  Game g;
  g.forsytheString("kr6/8/8/8/8/8/8/1RK5/");
  g.doNullMove();
  CheckSentry cs;
  cs.startObserving(&g);
  CPPUNIT_ASSERT(cs.isInCheck(Color::white()) == false);
  CPPUNIT_ASSERT(cs.isInCheck(Color::black()) == false);
  Square a1(2,7);
  Square b1(1,7);
  SmartPointer<Move> move = SimpleMove::createInstance(b1, a1);
  move->makeOn(g);
  CPPUNIT_ASSERT(cs.isInCheck(Color::white()) == true);
  CPPUNIT_ASSERT(cs.isInCheck(Color::black()) == false);
  move->takeBackOn(g);
  CPPUNIT_ASSERT(cs.isInCheck(Color::white()) == false);
  CPPUNIT_ASSERT(cs.isInCheck(Color::black()) == false);
  
};

void
CheckSentryTestCase::otherChecks()
{
  Game g;
  g.forsytheString("3k4/8/8/8/8/8/3r4/2KR4/w");
  CheckSentry cs;
  cs.startObserving(&g);
  CPPUNIT_ASSERT(!cs.isInCheck(Color::white()));
  CPPUNIT_ASSERT(!cs.isInCheck(Color::black()));
};

void
CheckSentryTestCase::castling()
{
  Game g;
  g.forsytheString("5k2/8/8/8/8/8/8/4K2R/w");
  CheckSentry cs;
  cs.startObserving(&g);
  CPPUNIT_ASSERT(!cs.isInCheck(Color::black()));
  Square e1(4,0);
  Square f1(5,0);
  Square g1(6,0);
  Square h1(7,0);
  CastlingMove m(e1, g1, h1, f1);
  m.makeOn(g);
  CPPUNIT_ASSERT(cs.isInCheck(Color::black()));
};

void
CheckSentryTestCase::enPassant()
{
  Game g;
  g.forsytheString("k7/8/8/b7/p7/8/1P6/4K3/w");
  CheckSentry cs;
  cs.startObserving(&g);
  CPPUNIT_ASSERT(cs.isInCheck(Color::white()));
  Square b2(1,1);
  Square b4(1,3);
  Square a4(0,3);
  Square b3(1,2);
  DoubleStep* move1 = DoubleStep::createInstance(b2, b4, b3);
  EnPassantMove move2(a4, b3, b4);
  move1->makeOn(g);
  CPPUNIT_ASSERT(!cs.isInCheck(Color::white()));
  move2.makeOn(g);
  CPPUNIT_ASSERT(cs.isInCheck(Color::white()));
};

Test*
CheckSentryTestCase::suite()
{
  TestSuite* testSuite = new TestSuite("GameTestCase");
  AddTest(testSuite, CheckSentryTestCase, findKings);
  AddTest(testSuite, CheckSentryTestCase, simpleChecks);
  AddTest(testSuite, CheckSentryTestCase, queenChecks);
  AddTest(testSuite, CheckSentryTestCase, rookChecks);
  AddTest(testSuite, CheckSentryTestCase, otherChecks);
  AddTest(testSuite, CheckSentryTestCase, castling);
  AddTest(testSuite, CheckSentryTestCase, enPassant);
  return testSuite;
};
