#!/usr/bin/perl
# $Id: tourney.pl 430 2007-08-19 19:47:12Z holger $
#
# Copyright (C) 2005-2007 Holger Ruckdeschel <holger@hoicher.de>
#
# 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., 51 Franklin Street, Fifth Floor, Boston,
# MA 02110-1301, USA.
#

use warnings;
use strict;

use File::Basename;
use File::Glob ':glob';
use Getopt::Std;
use Term::ReadLine;

# Added for debian distr by ok@xynyx.de
use lib '/usr/share/tourney-manager/';
use Tourney;
use Crosstable;

###############################################################################

my $verbose = 0;
my $debug = 0;

###############################################################################
# Parse command line
###############################################################################

my %opts;
getopts('Vvd', \%opts);


if (defined($opts{V})) {
	Tourney::print_version();
	exit(0);
}

if (defined($opts{v})) {
	$verbose = 1;
	$Tourney::verbose = 1;
}

if (defined($opts{d})) {
	$debug = 1;
	$Tourney::debug = 1;
}

###############################################################################

$SIG{'INT'} = 'IGNORE';

my $quit = 0;


my %commands = (
	help =>		\&cmd_help,
	quit =>		\&cmd_quit,
	tourney =>	\&cmd_tourney,
	clear =>	\&cmd_clear,
	create =>	\&cmd_create,
	update =>	\&cmd_update,
	print =>	\&cmd_print,
	start =>	\&cmd_start,
	stop =>		\&cmd_stop,
	crosstable =>	\&cmd_crosstable,
	replay =>	\&cmd_replay,
);

my %command_help = (
	###
	help =>		"display help about commands\n",
	###
	quit =>		"quits tourney manager\n",
	###
	tourney =>	<<EOF
switch tourney

Usage: tourney <name>

Switches to tourney '<name>'.
EOF
	,
	###
	clear =>	<<EOF
clear state of current tourney

Removes the state of the current tourney.
Additionally, the arguments '+pgns' and/or '+logs' may be given, which will
remove also the PGN and/or log files of the tourney.
EOF
	,
	###
	create =>	"initialize tourney, create tourney state\n",
	###
	update =>	"re-read configuration file, update tourney\n",
	###
	print =>	"display current tourney state\n",
	###
	start =>	"starts tourney\n",
	###
	stop =>		<<EOF
interrupts tourney

'stop' interrupts the tourney immediately after the current game.
'stop turn' interrupts the tourney after the current turn as finished.
EOF
	,
	###
	crosstable =>	"print current crosstable of tourney\n",
	###
	replay =>	<<EOF
replay single game or whole match

Usage: replay <matchnr>			Replay whole match
       replay <matchnr> <gamenr>	Replay single game
EOF
	,
	###
);


sub shell {
	print(<<EOF
Type 'help' for a list of available commands.
Type 'help <command>' for detailed help about a specific command.

EOF
	) if (-t STDIN);

	if (defined($ARGV[0])) {
		$Tourney::tourney_name = $ARGV[0];
	}

	my $readline;
	if (-t STDIN) {
		$readline = new Term::ReadLine($0);
	}

	while (!$quit) {
		my $prompt;
		if ($Tourney::runner_running) {
			$prompt = "$Tourney::tourney_name [running]> ";
		} elsif (Tourney::is_locked()) {
			$prompt = "$Tourney::tourney_name [locked]> ";
		} else {		
			$prompt = "$Tourney::tourney_name> ";
		}

		my $input;		
		if (-t STDIN) {
			$input = $readline->readline($prompt);
		} else {
			$input = <STDIN>;
		}
		
		if (!$input) {
			if (! -t STDIN) {
				$quit = 1;
			}
			next;
		}

		chomp($input);
		process_command($input);
	}
}

sub process_command {
	my ($input) = @_;

	if (!$input) {
		return;
	}

	my @args = split(/[ \t]+/, $input);
		
	if (defined($commands{$args[0]})) {
		&{$commands{$args[0]}}(@args);
	} else {
		print("Unknown command: $args[0]\n");
	}
}

print_version();
print("\n");
shell();
exit(0);

######################################################################

sub cmd_help {
	if ($_[1]) {
		if (defined($command_help{$_[1]})) {
			print("$_[1] -- $command_help{$_[1]}");
		} else {
			print("No help available for command '$_[1]'.\n");
		}
	} else {
		print_version();
		print("\n");

		my @c = sort(keys(%commands));
		print("Available commands: @c\n");
	}
}

sub cmd_quit {
	if ($Tourney::runner_running) {
		print("Runner thread still running. Use 'stop' first.\n");
		return;
	}

	$quit = 1;
}

sub cmd_tourney {
	if ($Tourney::runner_running) {
		print("Runner thread still running. Use 'stop' first.\n");
		return;
	}
	
	if (defined($_[1])) {
		$Tourney::tourney_name = $_[1];
	}

	print("Current tourney: $Tourney::tourney_name\n");
}

sub cmd_clear {
	my $args = {};
	while (defined($_[1])) {
		if ($_[1] eq '+logs') {
			$args->{delete_logs} = 1;
		} elsif ($_[1] eq '+pgns') {
			$args->{delete_pgns} = 1;
		}
		shift;
	}			
		
	clear_tourney($args);
}

sub cmd_create {
	create_tourney();
}

sub cmd_update {
	update_tourney();
}

sub cmd_print {
	print_tourney();
}
	
sub cmd_start {
	my $nr_threads = 1;
	if (defined($_[1])) {
		$nr_threads = $_[1];
	}

	if (start_tourney($nr_threads)) {
		# Wait a bit, so that thread's output will not disturb
		# our input prompt too much.
		sleep(2);
	}
}

sub cmd_stop {
	shift(@_);
	stop_tourney(@_);
}

sub cmd_crosstable {
	# TODO Perhaps this should also go into Tourney.pm.
	my @pgnfiles = bsd_glob($Tourney::tourney_name . ".match-*-*.pgn");
	Crosstable::print({ pgnfiles => \@pgnfiles });
}

sub cmd_replay {
	if (!defined($_[1])) {
		print("This command requires at least on argument.\n");
		return;
	} elsif ($_[1] !~ /^\d+$/) {
		print("Illegal argument: $_[1]\n");
		return;
	} elsif (defined($_[2]) && $_[2] !~ /^\d+$/) {
		print("Illegal argument: $_[2]\n");
		return;
	}
		
	Tourney::replay_game($_[1], $_[2]);
}
