#include <stdlib.h>

#include "util.h"
#include "board.h"
#include "searchstats.h"
#include "ttable.h"
#include "ptable.h"
#include "book.h"
#include "input.h"
#include "searchparams.h"
#include "protocol.h"
#include "genmove.h"
#include "iterate.h"
#include "move.h"
#include "log.h"
#include "ttable.h"
#include "uci.h"
#include "cmd.h"
#include "search.h"


void DoComputerMove(uci_t *uci){      

    board_t board[1];
    movelist_t movelist[1];
    searchstats_t searchstats[1];
    searchparams_t searchparams[1];

    int state;
    char SANmv[SANSZ];
    char LANmv[SANSZ];
    leaf *l;

    SearchStatsInit(searchstats);
    if(uci){
	SearchParamsCreateUci(searchparams,uci);
	BoardCopy(board,uci->board);
    }else{
	BoardFromGame(board,Protocol->game,BOARD_LAST);
	ASSERT(BoardValidate(board)==0);
	SearchParamsCreate(searchparams,Protocol);
	ASSERT(Protocol->computer==board->side);

    }
  
    GenMoves (board,movelist);
  
  
    l=NULL;
    if (!searchparams->infinite && movelist->gencnt == 1){
	OutputConsole("Single move!\n");
	l= movelist->moves;
	searchstats->RootPV=l->move;
	searchstats->RootPVSeq->moves[0]=l->move;
	searchstats->RootPVSeq->gencnt=1;
	searchstats->ElapsedTime=0.0;
    }
    if(!searchparams->infinite && !l && OptionGetBool(Option,"OwnBook")){
	BookQuery(Book,board,movelist);
	if(OptionGetBool(Option,"BookRandom")){
	    l=MoveListPickRandom(movelist);
	}else{
	    l=MoveListPickBest(movelist);
	}
	if(l){
	    OutputConsole("BookMove!\n");
	    if(Protocol->console){
		MoveListShow(board,movelist);
	    }
	    searchstats->RootPV=l->move;
	    searchstats->RootPVSeq->moves[0]=l->move;
	    searchstats->RootPVSeq->gencnt=1;
	    searchstats->ElapsedTime=0.0;
	}
    }
    if(!l){
	OutputConsole("Thinking...\n");
	Iterate (board, searchparams, searchstats);
    }

    if(!uci){
	MoveToSAN (board,searchstats->RootPV,SANmv);
	Protocol->game->boards[board->GameCnt-Protocol->game->InitialGameCnt].move=searchstats->RootPV;
	Protocol->game->boards[board->GameCnt-Protocol->game->InitialGameCnt].et = searchstats->ElapsedTime;
	MoveMake(board, searchstats->RootPV);
	Protocol->game->RealGameCnt = board->GameCnt;
	if (Protocol->TCMove) {
	    if(Protocol->game->RealGameCnt>=Protocol->NextPeriod){
		Protocol->NextPeriod+=2*Protocol->TCMove;
	    }
	}
	Protocol->TimeLimit[board->side] -= searchstats->ElapsedTime;
	if (Protocol->TCinc != 0){
	    Protocol->TimeLimit[board->side] += Protocol->TCinc;
	}
	MoveToLAN(searchstats->RootPV,LANmv);
	Output("move %s\n", LANmv);

    
	if (Protocol->console){
	    if(!l){
		SearchStatsShow(searchstats);
		TTableStatsShow(TTable);
		PTableStatsShow(PTable);
	    }
	    BoardShow (board);
	}
	OutputConsole("\nMy move is : %s\n", SANmv);
    }else{
	ShowBestMove(searchstats);
    }
  
  
    state=BoardState(board);
    if(state==BOARD_WHITE_WINS){
	Output("1-0 {White Mates}\n");
	Protocol->game->result=R_WHITE_WINS;
    }else if(state==BOARD_BLACK_WINS){
	Output("0-1 {Black Mates}\n");
	Protocol->game->result=R_BLACK_WINS;
    }else if(state==BOARD_STALEMATE){
	Output("1/2-1/2 {stalemate}\n");
	Protocol->game->result=R_DRAW;
    }else if(state==BOARD_50MOVERULE){
	Output("1/2-1/2 {Draw by 50 move rule}\n");
	Protocol->game->result=R_DRAW;
    }else if(state==BOARD_3FOLD_REPETITION){
	Output("1/2-1/2 {Draw by 3-fold repetition}\n");
	Protocol->game->result=R_DRAW;
    }
  
    CLEAR (Protocol->state_flags, THINK);
  
}

void MainLoop(){
    board_t board[1];
    int do_ponder;
    searchstats_t searchstats[1];
    
    if (Protocol->console) {
	BoardFromGame(board,Protocol->game,BOARD_LAST);
	BoardShow (board);
    }
    while (!(Protocol->state_flags & QUIT)) {
	Log("Waiting for input...\n");
	InputWait();
	Log("Parsing input...\n");
	parse_input();
	if ((Protocol->state_flags & THINK) && 
	    !(Protocol->state_flags & MANUAL) && 
	    !(Protocol->game->result!=R_NORESULT) && 
	    !(Protocol->state_flags & QUIT)) {
	    DoComputerMove(NULL);
	}
	do_ponder=false; // make the compiler happy.

	if(InputLook()){
	    do_ponder=false;
	}else if(Protocol->state_flags & QUIT){
	    do_ponder=false;
	}else if(Protocol->state_flags & ANALYZE){
	    do_ponder=true;
	}else if(Protocol->game->RealGameCnt==Protocol->game->InitialGameCnt){
	    do_ponder=false;
	}else if(Protocol->state_flags & MANUAL){
	    do_ponder=false;
	}else if(Protocol->game->result!=R_NORESULT){
	    do_ponder=false;
	}else if(Protocol->state_flags & HARD){
	    do_ponder=true;
	}
	if(do_ponder){
	    searchparams_t searchparams[1];
	    BoardFromGame(board,Protocol->game,BOARD_LAST);
	    ASSERT(BoardValidate(board)==0);
	    SearchParamsCreate(searchparams,Protocol);
	    searchparams->infinite=true;
	    if(!(Protocol->state_flags & ANALYZE)){
		searchparams->ponder=true;
	    }
	    Log("Pondering, GameCnt = %d\n", board->GameCnt);
	    Iterate(board,searchparams,searchstats);
	    Log("Pondering ended, GameCnt = %d\n", board->GameCnt);
	    if(Protocol->state_flags&ANALYZE){
		SearchStatsShow(searchstats);
		TTableStatsShow(TTable);
		PTableStatsShow(PTable);
	    }
	}
    }
    InputCleanup();

}





