/***************************************************************************
 *             __________               __   ___.
 *   Open      \______   \ ____   ____ |  | _\_ |__   _______  ___
 *   Source     |       _//  _ \_/ ___\|  |/ /| __ \ /  _ \  \/  /
 *   Jukebox    |    |   (  <_> )  \___|    < | \_\ (  <_> > <  <
 *   Firmware   |____|_  /\____/ \___  >__|_ \|___  /\____/__/\_ \
 *                     \/            \/     \/    \/            \/
 *
 * Copyright (C) 2007-2009 Joshua Simmons <mud at majidejima dot 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 2
 * of the License, or (at your option) any later version.
 *
 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
 * KIND, either express or implied.
 *
 ****************************************************************************/

#include "game.h"
#include "types.h"
#include "board.h"
#include "goban.h"
#include "sgf.h"
#include "sgf_output.h"
#include "sgf_parse.h"
#include "sgf_storage.h"
#include "display.h"

static void pre_game_setup (void);

char save_file[SAVE_FILE_LENGTH];
bool game_dirty = false;      /* flag for unsaved changes */
bool autosave_dirty = false;  /* flag for unsaved changes which haven't even
                                 been autosaved yet */

int move_num = 0;

unsigned char current_player = BLACK;

struct header_t header;     /* game metadata header info */

void
set_game_modified (void)
{
    game_dirty = true;
    autosave_dirty = true;
}

bool
load_game (const char *filename)
{
    rb->memset (&header, 0, sizeof (header));

    if (rb->strlen (filename) + 1 > SAVE_FILE_LENGTH)
    {
        DEBUGF ("file name too long\n");
        return false;
    }

    if (!rb->file_exists (filename))
    {
        DEBUGF ("file doesn't exist!\n");
        return false;
    }

    pre_game_setup ();

    rb->strcpy (save_file, filename);

#ifdef HAVE_ADJUSTABLE_CPU_FREQ
    rb->cpu_boost (true);
#endif

    rb->splash (0, "Loading...");

    bool parse_failed = false;
    if (!parse_sgf (save_file))
    {
        rb->splash (3 * HZ, "Unable to parse SGF file.  Will overwrite.");
        parse_failed = true;
    }

    game_dirty = false;
    autosave_dirty = false;

#ifdef HAVE_ADJUSTABLE_CPU_FREQ
    rb->cpu_boost (false);
#endif

    if (header.handicap >= 2)
    {
        current_player = WHITE;
    }

    post_game_setup_sgf ();

    if (!parse_failed)
    {
        draw_screen_display();
        if (rb->strcmp(filename, DEFAULT_SAVE))
        {
            metadata_summary();
        }
    }

    return true;
}


bool
save_game (const char *filename)
{
    if (rb->strlen (filename) + 1 > SAVE_FILE_LENGTH)
    {
        return false;
    }

    /* We only have to do something if the game is dirty, or we're being
       asked to save to a different location than we loaded from.

       If the game isn't dirty and we're being asked to save to default,
       we also don't have to do anything.*/
    if (!game_dirty &&
        (rb->strcmp (filename, save_file) == 0 ||
         rb->strcmp (filename, DEFAULT_SAVE) == 0))
    {
        return true;
    }

#ifdef HAVE_ADJUSTABLE_CPU_FREQ
    rb->cpu_boost (true);
#endif

    rb->splash (0, "Saving...");

    if (output_sgf (filename))
    {
        /* saving only "cleans" the game if it's not a save to default,
         * or if our save_file is actually default
         *
         * (so autosaves won't prevent legitimate saves to a Save As or
         * loaded file)
         */
        if (rb->strcmp (filename, DEFAULT_SAVE) ||
            rb->strcmp (save_file, DEFAULT_SAVE) == 0)
        {
            game_dirty = false;
        }

        /* but saving anywhere means that autosave isn't dirty */
        autosave_dirty = false;

#ifdef HAVE_ADJUSTABLE_CPU_FREQ
        rb->cpu_boost (false);
#endif
        /* The save succeeded.  Now, if we saved to an actual file (not to the
         * DEFAULT_SAVE), then we should delete the DEFAULT_SAVE file because
         * the changes stored in it are no longer unsaved.
         */
        if (rb->strcmp (filename, DEFAULT_SAVE))
        {
            rb->remove(DEFAULT_SAVE);
        }

        return true;
    }
    else
    {
#ifdef HAVE_ADJUSTABLE_CPU_FREQ
        rb->cpu_boost (false);
#endif
        return false;
    }
}


static void
pre_game_setup (void)
{
    rb->memset (&header, 0, sizeof (header));

    clear_caches_sgf ();
    free_tree_sgf ();

    set_size_board (MAX_BOARD_SIZE, MAX_BOARD_SIZE);

    clear_board ();

    game_dirty = true;
    move_num = 0;

    play_mode = MODE_PLAY;

    rb->strcpy (save_file, DEFAULT_SAVE);

    header_marked = false;
}


bool
setup_game (int width, int height, int handicap, int komi)
{
    pre_game_setup ();

    if (!set_size_board (width, height))
    {
        return false;
    }

    clear_board ();

    /* place handicap */
    if (handicap >= 2)
    {
        current_player = WHITE;
    }
    else if (handicap < 0)
    {
        return false;
    }
    else
    {
        current_player = BLACK;
    }

    header.handicap = handicap;
    setup_handicap_sgf ();

    header.komi = komi;

    post_game_setup_sgf ();

    return true;
}
