/*
    Protector -- a UCI chess engine

    Copyright (C) 2009-2010 Raimund Heid (Raimund_Heid@yahoo.com)

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.

*/

#ifndef _pgn_h_
#define _pgn_h_

#include <stdio.h>

typedef struct
{
   long *index;
   long indexSize;
   long numGames;
   FILE *file;
}
PGNFile;

#define PGN_ROASTERLINE_SIZE 256

typedef struct
{
   Square from, to;
   Piece newPiece;
   Position position;
   void *previousMove;
   void *nextMove;
   void *alternativeMove;

   char *comment, *glyphs;
}
Gamemove;

typedef struct
{
   char event[PGN_ROASTERLINE_SIZE];
   char site[PGN_ROASTERLINE_SIZE];
   char date[PGN_ROASTERLINE_SIZE];
   char round[PGN_ROASTERLINE_SIZE];
   char white[PGN_ROASTERLINE_SIZE];
   char black[PGN_ROASTERLINE_SIZE];
   char result[PGN_ROASTERLINE_SIZE];
   char setup[PGN_ROASTERLINE_SIZE];
   char fen[PGN_ROASTERLINE_SIZE];
   char whiteTitle[PGN_ROASTERLINE_SIZE];
   char blackTitle[PGN_ROASTERLINE_SIZE];
   char whiteElo[PGN_ROASTERLINE_SIZE];
   char blackElo[PGN_ROASTERLINE_SIZE];
   char eco[PGN_ROASTERLINE_SIZE];
   char nic[PGN_ROASTERLINE_SIZE];
   char timeControl[PGN_ROASTERLINE_SIZE];
   char termination[PGN_ROASTERLINE_SIZE];

   char *moveText;
   Gamemove *firstMove, *lastMove;
}
PGNGame;

/**
 * Open the PGN file specified by 'filename'.
 *
 * @return 0 if the file could be opened without any error
 */
int openPGNFile(PGNFile * pgnfile, const char *filename);

/**
 * Close the PGN file specified by 'pgnfile'.
 */
void closePGNFile(PGNFile * pgnfile);

/**
 * Get the PGNGame specified by 'number'.
 *
 * @param number the number of the game to be loaded [1...pgnfile.numGames]
 * @param pgngame the struct supposed to contain the game data. It is 
 *        important to free the memory allocated for the game moves as
 *        soon as the pgngame is no longer needed.
 *
 * @return 0 if no errors occured
 */
PGNGame *getGame(PGNFile * pgnfile, int number);

/**
 * Initialize the specified PGNGame.
 */
void initializePGNGame(PGNGame * game);

/**
 * Free all memory allocated for the specified pgn game.
 */
void resetPGNGame(PGNGame * game);

/**
 * Free all memory allocated for the specified pgn game 
 * (including the game itself).
 */
void freePgnGame(PGNGame * game);

/**
 * Generate the SAN notation of the specified move.
 */
void generateMoveText(Variation * variation, const Move move, char *pgnMove);

/**
 * Get the current principal variation of the specified variation.
 *
 * @return a newly allocated string
 */
char *getPrincipalVariation(const Variation * variation);

/**
 * Generate the pgn text of the specified game.
 */
char *generatePgn(PGNGame * game);

/**
 * Initialize a variation with the specified game.
 */
void initializeVariationFromGame(Variation * variation, PGNGame * game);

/**
 * Initialize a game with the specified variation.
 */
void initializeGameFromVariation(const Variation * variation, PGNGame * game,
                                 bool copyPv);
/**
 * Convert a gamemove to a move.
 */
Move gameMove2Move(const Gamemove * gamemove);

/**
 * Interpret the given pgn move and return an appropriate Move.
 */
Move interpretPGNMove(const char *moveText, PGNGame * game);

/**
 * Append the specified move to the specified game. If the move
 * is found to be illegal this call has no effect on the game and
 * a nonzero value will be returned.
 *
 * @return 0 if and only if the specified move was legal
 */
int appendMove(PGNGame * game, const Move move);

/**
 * Take back the last move of the specified game.
 */
void takebackLastMove(PGNGame * game);

/**
 * Initialize this module.
 *
 * @return 0 if no errors occurred.
 */
int initializeModulePgn(void);

/**
 * Test this module.
 *
 * @return 0 if all tests succeed.
 */
int testModulePgn(void);

#endif
