# include "TestSanNotation.h"
# include "Game/Game.h"
# include "Moves/SimpleMove.h"
# include "Moves/CapturingMove.h"
# include "Moves/PromotingMove.h"
# include <Moves/PromotingCapture.h>
# include "Color.h"
# include <string>
# include <Moves/SanNotation.h>
using namespace Alice;
Test*
TestSanNotation::suite()
{
  TestSuite* result = new TestSuite("TestSanNotation");
  AddTest(result, TestSanNotation, simpleMove);
  AddTest(result, TestSanNotation, pawnMove);
  AddTest(result, TestSanNotation, capturingMove);
  AddTest(result, TestSanNotation, promotingMove);
  AddTest(result, TestSanNotation, promotingCapture);
  AddTest(result, TestSanNotation, mate);
  AddTest(result, TestSanNotation, ambiguous);
  AddTest(result, TestSanNotation, ambiguous2);
  //  AddTest(result, TestSanNotation, fitsDescription);
  AddTest(result, TestSanNotation, pawnCapture);
  AddTest(result, TestSanNotation, fromString);
  return result;
  
};

void
TestSanNotation::simpleMove()
{
  Game g;
  SmartPointer<Move>  m = SimpleMove::createInstance(Square(1,0), Square(2,2));
  SanNotation san(m, g);
  CPPUNIT_ASSERT_EQUAL(std::string("Nc3"), san.getString());
  CPPUNIT_ASSERT(san.getMove() == m);
};

void
TestSanNotation::pawnMove()
{
  Game g;
  SmartPointer<Move> m = SimpleMove::createInstance(Square(4,1), 
							 Square(4,3));
  SanNotation san(m, g);
  CPPUNIT_ASSERT_EQUAL(std::string("e4"), san.getString());
};

void
TestSanNotation::capturingMove()
{
  Game g;
  g.forsytheString("Rr6/8/8/8/8/8/8/K6k/w");
  SmartPointer<Move> m = new CapturingMove(Square(0,7), Square(1,7));
  SanNotation san(m, g);
  CPPUNIT_ASSERT_EQUAL(std::string("Rxb8"), san.getString());
};

void
TestSanNotation::promotingMove()
{
  Game g;
  g.forsytheString("8/P7/8/8/8/8/8/K6k/w");
  SmartPointer<Move> m = 
    new PromotingMove(Square(0,6), 
		      Square(0,7), 
		      Piece::newQueen(Color::white()));
  SanNotation san(m, g);
  CPPUNIT_ASSERT_EQUAL(std::string("a8=Q+"), san.getString());
};

void
TestSanNotation::promotingCapture()
{
  //  CPPUNIT_ASSERT(false);
  Game g;
  g.forsytheString("r7/1P6/8/8/8/8/8/K6k/w");
  SmartPointer<Move> m = 
    new PromotingCapture(Square(1,6), 
		      Square(0,7), 
		      Piece::newQueen(Color::white()));
  SanNotation san(m, g);
  CPPUNIT_ASSERT_EQUAL(std::string("bxa8=Q+"), san.getString());
};

void
TestSanNotation::mate()
{
  Game g;
  g.forsytheString("k7/8/K7/8/8/8/8/7R/w");
  SmartPointer<Move> m
    = SimpleMove::createInstance(Square(7,0), Square(7,7));
  std::string wanted("Rh8#");
  SanNotation san(m, g);
  std::string actual( san.getString() );
  CPPUNIT_ASSERT_EQUAL( wanted, actual );
}

void
TestSanNotation::ambiguous()
{
  Game g;
  g.forsytheString("K6k/8/8/8/8/5N2/8/1N6/w");
  SmartPointer<Move>  m = 
    SimpleMove::createInstance(Square(1,0),Square(3,1));
  SanNotation san(m, g);
  CPPUNIT_ASSERT_EQUAL(std::string("Nbd2"), san.getString());
};

void
TestSanNotation::ambiguous2()
{
  Game g;
  g.forsytheString("R7/n7/R7/8/8/8/8/K6k/w");
  SmartPointer<Move> m = new CapturingMove(Square(0,7), Square(0,6));
  SanNotation san(m, g);
  CPPUNIT_ASSERT_EQUAL(std::string("R8xa7"), san.getString());
  //CPPUNIT_ASSERT(false);
};

void
TestSanNotation::fitsDescription()
{
  Game g;
  g.forsytheString("k6K/8/8/8/8/8/8/N1N5/w");
  SmartPointer<Move> move1 = 
    SimpleMove::createInstance(Square(0,0), Square(1,2));
  SmartPointer<Move> move2 = 
    SimpleMove::createInstance(Square(2,0), Square(1,2));
  SmartPointer<Move> move3 = 
    SimpleMove::createInstance(Square(0,4), Square(1,2));
  SanNotation san(move1, g);
    CPPUNIT_ASSERT(san.fitsDescription(*move1));
  CPPUNIT_ASSERT(san.fitsDescription(*move2));
  CPPUNIT_ASSERT(san.fitsDescription(*move3));
  san.setFile();
  
  CPPUNIT_ASSERT(san.fitsDescription(*move1));
  CPPUNIT_ASSERT(!san.fitsDescription(*move2));
  CPPUNIT_ASSERT(san.fitsDescription(*move3));
  san.setRank();
  
  CPPUNIT_ASSERT(san.fitsDescription(*move1));
  CPPUNIT_ASSERT(!san.fitsDescription(*move2));
  
  CPPUNIT_ASSERT(!san.fitsDescription(*move3));
}

void
TestSanNotation::pawnCapture()
{
  Game g ;
  g.forsytheString("k6K/8/8/8/3p4/4P3/8/8/w");
  SmartPointer<Move> m = new CapturingMove(Square(4,2), Square(3,3));
  SanNotation san(m, g);
  CPPUNIT_ASSERT_EQUAL(std::string("exd4"), san.getString());
};

void
TestSanNotation::fromString()
{
  Game g;
  SanNotation san("Nf3", g);
  CPPUNIT_ASSERT(san.isValid());
  SmartPointer<Move> move = san.getMove();
  const Square g1(6,0);
  const Square f3(5,2);
  CPPUNIT_ASSERT(g1 == move->source());
  CPPUNIT_ASSERT(f3 == move->destination());

  g.forsytheString("k7/8/K7/7R/8/8/8/8/w");
  SanNotation san2("Rh8#", g);
  CPPUNIT_ASSERT(san2.isValid());
};
