/*----------------------------------------------------------------------
 | DIKSIO.C							940429
 |
 | Contains all disk I/O functions.
 +----------------------------------------------------------------------*/


#include "var.h"


static Boolean  OpenFileForWriting(FILE ** fp, char *name);
static Boolean  OpenFileForReading(FILE ** fp, char *name);
static Signed2  GetLine(FILE * fp, char *s);


/*----------------------------------------------------------------------
 | SaveGame							940429
 |
 | Saves the starting position and the resulting game moves.
 +----------------------------------------------------------------------*/
void            SaveGame(char *filename)
{
    Signed2         nr,
                    i;
    char            name[MaxFileNameLength],
                    s[MaxCommandLength];
    FILE           *fp;

    if (filename[0] == '\0') {
        printf("ERROR: filename required\n");
        printf("Game not saved\n");
    } else {
        strcpy(name, GameDirectory);
        strcat(name, filename);
        if (FileExists(name)) {
            printf("File already exists, overwrite (Y/N) ? ");
            do {
                gets(s);
                if (tolower(s[0]) == 'n') {
                    printf("Game not saved\n");
                    return;
                }
            }
            while (tolower(s[0]) != 'y');
        }
        if (OpenFileForWriting(&fp, name)) {
            printf("Game not saved\n");
            return;
        }
        /* take back all moves */
        nr = nrGamePlies;
        for (i = 0; i < nr; i++) {
            UndoMove();
        }
        /* save starting position and game */
        for (i = 0; i < nrPieces[White]; i++) {
            SPrintSquare(s, pieces[White][i].square);
            fprintf(fp, "%c%s ",
                    IsPawn(pieces[White][i].type) ? ' ' :
                    pieceSymbol[pieces[White][i].type], s);
        }
        fprintf(fp, "\n");
        for (i = 0; i < nrPieces[Black]; i++) {
            SPrintSquare(s, pieces[Black][i].square);
            fprintf(fp, "%c%s ",
                    IsPawn(pieces[Black][i].type) ? ' ' :
                    pieceSymbol[pieces[Black][i].type | White], s);
        }
        fprintf(fp, "\n");
        if (epSquare[0] == NoEp) {
            s[0] = '\0';
        } else {
            SPrintSquare(s, epSquare[0]);
        }
        fprintf(fp, "%s %s ", moveColorString[toMove], s);
        if (castling[nrGamePlies] & WhiteShort) {
            fprintf(fp, "WS ");
        }
        if (castling[nrGamePlies] & WhiteLong) {
            fprintf(fp, "WL ");
        }
        if (castling[nrGamePlies] & BlackShort) {
            fprintf(fp, "BS ");
        }
        if (castling[nrGamePlies] & BlackLong) {
            fprintf(fp, "BL ");
        }
        fprintf(fp, "\n");
        /* execute all moves */
        for (i = 0; i < nr; i++) {
            if (i % 2 == 0) {
                fprintf(fp, "%3d.", i / 2 + 1);
            }
            fprintf(fp, "%s ", gameString[i]);
            if (i % 8 == 7) {
                fprintf(fp, "\n");
            }
            DoMove(&(game[i]));
        }
        fprintf(fp, "\n");
        fclose(fp);
        printf("Game saved\n");
    }                           /* else */
}                               /* SaveGame */


/*----------------------------------------------------------------------
 | LoadGame							940429
 |
 | Loads a position and the resulting game moves.
 +----------------------------------------------------------------------*/
void            LoadGame(char *filename)
{
    Signed2         i;
    char            name[MaxFileNameLength],
                    s[MaxCommandLength];
    char           *ptr,
                    string[MaxCommandLength];
    char            temp[MaxCommandLength],
                   *p;
    FILE           *fp;
    Boolean         stop,
                    initialPos;

    if (filename[0] == '\0') {
        printf("ERROR: filename required\n");
        goto ErrorLabel;
    } else {
        strcpy(name, GameDirectory);
        strcat(name, filename);
        if (OpenFileForReading(&fp, name)) {
            goto ErrorLabel;
        }
        EmptyBoard();
        /* load starting position and game */
        /* white pieces */
        if (GetLine(fp, s)) {
            printf("ERROR: file too small\n");
            goto ErrorLabel;
        }
        sscanf(s, "%s", string);
        if (strlen(string) > 3 ||
            strchr(string, '.') != NULL) {      /* Assume it is a move */
            initialPos = True;
            StartingPosition();
        } else {
            initialPos = False;
            ptr = s;
            SkipSpaces(ptr);
            while (ptr[0] != '\0') {
                string[0] = 'w';
                sscanf(ptr, "%s", &(string[1]));
                PerformPlacePiece(string);
                ptr += strlen(string) - 1;
                SkipSpaces(ptr);
            }
            /* black pieces */
            if (GetLine(fp, s)) {
                printf("ERROR: file too small\n");
                goto ErrorLabel;
            }
            ptr = s;
            SkipSpaces(ptr);
            while (ptr[0] != '\0') {
                string[0] = 'b';
                sscanf(ptr, "%s", &(string[1]));
                PerformPlacePiece(string);
                ptr += strlen(string) - 1;
                SkipSpaces(ptr);
            }
            if (GetLine(fp, s)) {
                printf("ERROR: file too small\n");
                goto ErrorLabel;
            }
            ptr = s;
            /* color to move */
            sscanf(ptr, "%s", string);
            if (strcmp(string, moveColorString[White]) == 0) {
                toMove = White;
            } else if (strcmp(string, moveColorString[Black]) == 0) {
                toMove = Black;
            } else {
                printf("ERROR: unknown color in '%s'\n", string);
                goto ErrorLabel;
            }
            ptr += strlen(string);
            SkipSpaces(ptr);
            string[0] = '\0';
            /* ep square */
            sscanf(ptr, "%s", string);
            if (string[0] == '\0' ||
                tolower(string[1]) == 's' || tolower(string[1]) == 'l') {
                epSquare[0] = NoEp;
            } else {
                epSquare[0] = Square(tolower(string[0]) - 'a' + A, string[1] - '0');
                ptr += strlen(string);
                SkipSpaces(ptr);
            }
            /* castlings */
            while (ptr[0] != '\0') {
                sscanf(ptr, "%s", string);
                if (tolower(string[0]) == 'w') {
                    if (tolower(string[1]) == 's') {
                        castling[0] |= WhiteShort;
                    } else if (tolower(string[1]) == 'l') {
                        castling[0] |= WhiteLong;
                    } else {
                        printf("ERROR: unknown castling in '%s'\n", string);
                        goto ErrorLabel;
                    }
                } else if (tolower(string[0]) == 'b') {
                    if (tolower(string[1]) == 's') {
                        castling[0] |= BlackShort;
                    } else if (tolower(string[1]) == 'l') {
                        castling[0] |= BlackLong;
                    } else {
                        printf("ERROR: unknown castling in '%s'\n", string);
                        goto ErrorLabel;
                    }
                } else {
                    printf("ERROR: unknown color in '%s'\n", string);
                    goto ErrorLabel;
                }
                ptr += strlen(string);
                SkipSpaces(ptr);
            }                   /* while */
        }                       /* else: read position */
        /* read and execute all moves */
        if (!initialPos) {
            s[0] = '\0';
        }
        ptr = s;
        SkipSpaces(ptr);
        stop = False;
        for (i = 0;; i++) {
            while (*ptr == '\0') {
                if (GetLine(fp, s)) {
                    stop = True;
                    break;
                }
                ptr = s;
                SkipSpaces(ptr);
            }
            if (stop) {
                break;
            }
            sscanf(ptr, "%s", temp);
            p = strchr(temp, '.');
            if (p != NULL) {
                if (p[1] == '\0') {
                    --i;
                } else {
                    strcpy(gameString[i], &(p[1]));
                    PerformMoveCommand(gameString[i]);
                }
            } else {
                strcpy(gameString[i], temp);
                PerformMoveCommand(gameString[i]);
            }
            ptr += strlen(temp);
            SkipSpaces(ptr);
        }
        fclose(fp);
        printf("Game loaded\n");
    }                           /* else */
    return;
ErrorLabel:
    printf("Game not loaded\n");
    EmptyBoard();
    StartingPosition();
    return;
}                               /* LoadGame */


/*----------------------------------------------------------------------
 | OpenFileForWriting						940429
 |
 | Opens file with name 'name' and creates handle '*fp'.
 +----------------------------------------------------------------------*/
static          Boolean
                OpenFileForWriting(FILE ** fp, char *name)
{
    if ((*fp = fopen(name, "w")) == NULL) {
        printf("ERROR: cannot open file '%s'\n", name);
        return (True);
    }
    return (False);
}                               /* OpenFileForWriting */


/*----------------------------------------------------------------------
 | OpenFileForReading						940429
 |
 | Opens file with name 'name' and creates handle '*fp'.
 +----------------------------------------------------------------------*/
static          Boolean
                OpenFileForReading(FILE ** fp, char *name)
{
    if ((*fp = fopen(name, "r")) == NULL) {
        printf("ERROR: cannot open file '%s'\n", name);
        return (True);
    }
    return (False);
}                               /* OpenFileForReading */


static          Signed2
                GetLine(FILE * fp, char *s)
{
    char           *ptr;

    for (;;) {
        if (fgets(s, MaxCommandLength, fp) == NULL) {
            return (1);
        }
        ptr = s;
        SkipSpaces(ptr);
        if (*ptr != '%') {      /* No comment line? */
            break;
        }
    }
    s[strlen(s) - 1] = '\0';
    return (0);
}                               /* GetLine */


void            SaveLatexPos(char *ptr)
{
    char            s[4],
                    filename[20];
    FILE           *fp;
    Signed2         i;

    if (*ptr == '\0') {
        strcpy(filename, "pos.tex");
    } else {
        strcpy(filename, ptr);
    }
    if (!OpenFileForWriting(&fp, filename)) {
        fprintf(fp, "\\maakstelling\n");
        fprintf(fp, "  {");
        for (i = 0; i < nrPieces[White]; i++) {
            if (!IsPawn(pieces[White][i].type)) {
                fprintf(fp, "%c",
                        toupper(pieceSymbol[pieces[White][i].type]));
            }
            SPrintSquare(s, pieces[White][i].square);
            fprintf(fp, "%s", s);
            if (i < nrPieces[White] - 1) {
                fprintf(fp, ", ");
            }
        }
        fprintf(fp, "}\n");

        fprintf(fp, "  {");
        for (i = 0; i < nrPieces[Black]; i++) {
            if (!IsPawn(pieces[Black][i].type)) {
                fprintf(fp, "%c",
                        toupper(pieceSymbol[pieces[Black][i].type]));
            }
            SPrintSquare(s, pieces[Black][i].square);
            fprintf(fp, "%s", s);
            if (i < nrPieces[Black] - 1) {
                fprintf(fp, ", ");
            }
        }
        fprintf(fp, "}\n");

        fprintf(fp, "  {Move %d (%s)}\n", (nrGamePlies) / 2 + 1,
                moveColorString[toMove]);
        fclose(fp);

        printf("Position saved in '%s'\n", filename);
    }
}                               /* SaveLatexPos */
