// -*- c++ -*-

# ifndef MoveText_h
# define MoveText_h
# include <list>
# include <Game/Game.h>
# include <Moves/Move.h>
# include <SmartPointer.h>
# include <iostream>
# include <sstream>
# include <Moves/SanNotation.h>
namespace Alice
{
  class MoveText
  {
  public:
    MoveText();
    Game& getGame();
    const Game& getGame() const;
    bool addMove(const std::string& move);
    void addMove(SmartPointer<Move> mv);
    int plyCount() const;
    void read( std::istream& in );
    void write( std::ostream& out );
    SmartPointer<Move> getMove( int ply );
    std::string getForsytheString( int ply );
    
    void beginVariation();
    void endVariation();
    void forward();
    void backward();
    void makeMove( std::ostream& out );
    bool checkMove( const std::string& s );
    void reset();
    SanNotation getLastMove();
  private:
    void writeRecursively( std::ostream& out );
    void readComment( std::istream& );
    Game _game;
    struct Node
    {
      Node* parent;
      Node* first;
      Node* next;
      SmartPointer<Move> move;
      std::string comment;
      Node()
	: parent(0),
	  first(0),
	  next(0)
      {};
      ~Node()
      {
	delete first;
	delete next;
      };
    };
    Node root;

    void goToNode( Node* n );
    Node* currentNode;
    std::stack<Node*> nodeStack;
    int currentPly;
    int column;
    template<typename T>
    std::ostream& writeItem( std::ostream& out, const T& item )
    {
      std::ostringstream stream;
      stream << item;
      std::string str = stream.str();
      int length = str.size();
      column += length;
      out << str;
      return out;
    }
    std::ostream& space(std::ostream& out)
    {
      if (column >= 75)
	{
	  out<<std::endl;
	  column = 0;
	}
      else
	{
	  out << " ";
	  column ++ ;
	}
      return out;
    }
  };
}; // namespace Alice
# endif // MoveText_h
