/*
 *  Copyright (C) 2006 Ludovic Jacomme (ludovic.jacomme@gmail.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 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, write to the Free Software
 *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */

#include <stdio.h>
#include <zlib.h>
#include "SDL.h"

#include <pspkernel.h>
#include <pspdebug.h>
#include <pspsdk.h>
#include <pspctrl.h>
#include <pspthreadman.h>

#include <pspwlan.h>
#include <pspkernel.h>
#include <psppower.h>

#include <stdlib.h>
#include <stdio.h>

#include "config.h"
#include "psp_global.h"
#include "psp_play.h"

static void
psp_play_init_sgf(Gameinfo *ginfo)
{
# if 0 /* TO_BE_DONE ! */
  if (sgf_initialized)
    return;
  sgf_initialized = 1;

  sgf_write_header(sgftree.root, 1, get_random_seed(), komi,
                         level, chinese_rules);
  sgfOverwritePropertyInt(sgftree.root, "HA", ginfo->handicap);

  if (ginfo->handicap > 0) {
    gnugo_recordboard(sgftree.root);
  }
# endif
}

static void
psp_play_init_all(int reset_only)
{
  clock_init(3600, 0, 0);

  if (reset_only) {
    sgftree_free(&GGO.sgftree);
  } else {
    sgftree_clear(&GGO.sgftree);
  }
  board_size = GGO.board_width;

  komi = 0.0;
  gameinfo_clear(&GGO.gameinfo, board_size, komi);

  int seed = getpid();
  if (! reset_only) {
    init_gnugo(DEFAULT_MEMORY, seed);
  }

  /* Initialize and empty sgf tree */
  sgftreeCreateHeaderNode(&GGO.sgftree, board_size, komi);

  GGO.gameinfo.game_record = GGO.sgftree;
  if (GGO.go_player_color == GGO_WHITE) GGO.gameinfo.computer_player = BLACK;
  else                                  GGO.gameinfo.computer_player = WHITE;

  GGO.gameinfo.handicap = GGO.go_handicap;

  int sz = 0;
  if (sgfGetIntProperty(GGO.sgftree.root, "SZ", &sz)) {
    gnugo_clear_board(sz);
  }

  if (GGO.gameinfo.handicap == 0)
    GGO.gameinfo.to_move = BLACK;
  else {
    GGO.gameinfo.handicap = gnugo_placehand(GGO.gameinfo.handicap);
    GGO.gameinfo.to_move  = WHITE;
  }
}

void
psp_play_init()
{
  psp_play_init_all(0);
}

void
psp_play_reset()
{
  psp_play_init_all(1);
  psp_play_update_board();
}

int
psp_play_computer_move()
{
  int x, y;
  int move_val;
# if 0
  int resignation_declined = 0;
  float upper_bound, lower_bound;
# endif

  Gameinfo *gameinfo = &GGO.gameinfo;

  psp_play_init_sgf(gameinfo);

  /* Generate computer move. */
  move_val = gnugo_genmove(&x, &y, gameinfo->to_move);

# if 0
  if (resignation_allowed && move_val < 0.0 && ON_BOARD2(x, y)) {
    int state = psp_play_endgame(gameinfo, 2);
    if (state != -1)
      return state;

    /* The opponent declined resignation. Remember not to resign again. */
    resignation_allowed = 0;
    resignation_declined = 1;
    move_val = -move_val;
  }

  if (showscore) {
    gnugo_estimate_score(&upper_bound, &lower_bound);
    current_score_estimate = (int) ((lower_bound + upper_bound) / 2.0);
  }
# endif
  if (move_val < 0.0 && ON_BOARD2(x,y)) {
    /* force game over */
    GGO.passes = 2;

    GGO.last_move_x = -1;
    GGO.last_move_y = -1;

    return 0;
  }
    
  GGO.last_move_x = x;
  GGO.last_move_y = y;
  
# if 0
  mprintf("%s(%d): %m\n", color_to_string(gameinfo->to_move), movenum+1, x, y);
# endif

  if (is_pass(POS(x, y))) GGO.passes++;
  else                    GGO.passes = 0;

  gnugo_play_move(x, y, gameinfo->to_move);
  sgffile_add_debuginfo(GGO.sgftree.lastnode, move_val);
  sgftreeAddPlay(&GGO.sgftree, gameinfo->to_move, x, y);
# if 0 
  if (resignation_declined)
    sgftreeAddComment(&sgftree, "GNU Go resignation was declined");
  sgffile_output(&sgftree);
# endif

  gameinfo->to_move = OTHER_COLOR(gameinfo->to_move);

  psp_play_update_board();

  return 1;
}

void
psp_play_update_board()
{
  int x;
  int y;

  for (y = 0; y < GGO.board_width; y++) {
    for (x = 0; x < GGO.board_width; x++) {

      int index = (y*GGO.board_width) + x;
      int stone = BOARD(x, y);

      if (stone == EMPTY) GGO.board_array[index] = GGO_EMPTY;
      else
      if (stone == BLACK) GGO.board_array[index] = GGO_BLACK;
      else
      if (stone == WHITE) GGO.board_array[index] = GGO_WHITE;
    }
  }
}

int
psp_play_player_move()
{
  Gameinfo *gameinfo = &GGO.gameinfo;

  int x = GGO.current_x;
  int y = GGO.current_y;

  if (!gnugo_is_legal(x, y, gameinfo->to_move)) {
    return 0;
  }

  GGO.passes = 0;

  psp_play_init_sgf(gameinfo);
  gnugo_play_move(x, y, gameinfo->to_move);

  sgffile_add_debuginfo(GGO.sgftree.lastnode, 0);
  sgftreeAddPlay(&GGO.sgftree, gameinfo->to_move, x, y);
  sgffile_output(&GGO.sgftree);

  GGO.last_move_x = x;
  GGO.last_move_y = y;
  
  psp_play_update_board();

  gameinfo->to_move = OTHER_COLOR(gameinfo->to_move);

  return 1;
}

int
psp_play_player_pass()
{
  Gameinfo *gameinfo = &GGO.gameinfo;

  GGO.passes++;

  psp_play_init_sgf(gameinfo);
  gnugo_play_move(-1, -1, gameinfo->to_move);

  sgffile_add_debuginfo(GGO.sgftree.lastnode, 0);
  sgftreeAddPlay(&GGO.sgftree, gameinfo->to_move, -1, -1);
  sgffile_output(&GGO.sgftree);

  gameinfo->to_move = OTHER_COLOR(gameinfo->to_move);

  psp_play_computer_move();

  return 1;
}
