#! /usr/bin/perl

use ccbs;
use strict;
use warnings;

ccbs::admin_only();

my $dbh = ccbs::db_connect();
my $cgi = new CGI;

my $tournament = $cgi->param('tournament');
my $round = $cgi->param('round');
my $num_random = $cgi->param('numrandom');
my $num_chosen = $cgi->param('numchosen');
my $num_groups = $cgi->param('numgroups');
my $num_qual = $cgi->param('numqual');

$dbh->{AutoCommit} = 0;

$dbh->do('INSERT INTO rounds (tournament, round, randomsongs, chosensongs, numqualifying) VALUES (?, ?, ?, ?, ?)',
	undef, $tournament, $round, $num_random, $num_chosen, $num_qual);

if ($num_groups == 1) {
	$dbh->do('INSERT INTO groups (tournament, round, parallel) VALUES (?, ?, ?)',
		undef, $tournament, $round, 0);
} else {
	for my $i (1..$num_groups) {
		$dbh->do('INSERT INTO groups (tournament, round, parallel) VALUES (?, ?, ?)',
			undef, $tournament, $round, $i);
	}
}

# Seed people into groups (quite preliminary for now)
my $people;
if ($round == 1) {
	$people = ccbs::db_fetch_all($dbh, 'SELECT * FROM players WHERE player IN ( SELECT player FROM tournamentparticipation WHERE tournament=? ) ORDER BY random()',
		$tournament);
} else {
	# First of all, check that there are no null values!
	my $ref = $dbh->selectrow_hashref('SELECT COUNT(*) AS num_incomplete FROM scores WHERE tournament=? AND round=? AND (song IS NULL OR playmode IS NULL OR difficulty IS NULL OR chosen IS NULL or score IS NULL)', undef, $tournament, $round-1);
	if ($ref->{'num_incomplete'} != 0) {
		ccbs::user_error(_("There's still") . $ref->{'num_incomplete'} . _("songs left in this round which don't have all data registered."));
	}

	# Find out how many people will go on from the _current_ group (ie. the one
	# before the one we just inserted)
	my $ref = $dbh->selectrow_hashref('SELECT numqualifying FROM rounds WHERE tournament=? AND round=?',
		undef, $tournament, $round - 1);
	my $num_qual_prev = $ref->{'numqualifying'};

	# Get the total list of scores for each player in this round, and pick
	# out the best N
	$people = [];
	my $q = $dbh->prepare('SELECT parallel,player,SUM(score)/SUM(CASE WHEN chosen THEN 10 ELSE feetrating END) AS score FROM scores NATURAL JOIN tournaments NATURAL JOIN max_single_feetrating WHERE tournament=? AND round=? GROUP BY parallel,player ORDER BY parallel, SUM(score) DESC');
	$q->execute($tournament, $round - 1);
	
	my ($parallel,$num_from_this_parallel);

	while (my $ref = $q->fetchrow_hashref()) {
		if (!defined($parallel) || $parallel != $ref->{'parallel'}) {
			$parallel = $ref->{'parallel'};
			$num_from_this_parallel = 0;
		}
		if ($num_from_this_parallel++ < $num_qual_prev) {
			push @$people, {%$ref};
		}
	}
}

if ($num_groups == 1) {
	# Everybody's in the same group
	my @speople = sort { $a->{'score'} <=> $b->{'score'} } @$people;

	my $position = 1;
	for my $p (@speople) {
		$dbh->do('INSERT INTO roundparticipation (tournament, round, parallel, player, position) VALUES (?, ?, ?, ?, ?)', undef,
			$tournament, $round, 0, $p->{'player'}, $position);
		$position++;
	}
} else {
	# Zigzag people to get the most fair groups possible
	my @speople = sort { $b->{'score'} <=> $a->{'score'} } @$people;

	my @ngroups = ();
	for my $g (1..$num_groups) {
		push @ngroups, [];
	}
	
	my $group = 0;
	my $direction = 1;
	for my $p (@speople) {
		push @{$ngroups[$group]}, $p->{'player'};
		if ($group + $direction < 0 || $group + $direction >= $num_groups) {
			$direction = -$direction;
		} else {
			$group += $direction;
		}
	}

	$group = 1;
	for my $g (@ngroups) {
		my @gpeople = reverse @$g;
		for my $position (0..$#gpeople) {
			$dbh->do('INSERT INTO roundparticipation (tournament, round, parallel, player, position) VALUES (?, ?, ?, ?, ?)', undef,
				$tournament, $round, $group, $gpeople[$position], $position + 1);
		}
		$group++;
	}
}

# Pick random songs for the groups (don't pick challenge-only songs; slightly
# clumsy, should we have used an IN subquery instead?)
for my $g (1..$num_groups) {
	my $gg = ($num_groups == 1) ? 0 : $g;

	for my $s (1..$num_random) {
		my $ref = $dbh->selectrow_hashref('SELECT * FROM machinesongs NATURAL JOIN songratings WHERE song NOT IN ( SELECT song FROM randomsongsused ) AND machine=( SELECT machine FROM tournaments WHERE tournament=? ) AND playmode=\'single\' AND difficulty=\'expert\' ORDER BY random() LIMIT 1',
			undef, $tournament);
		if (!defined($ref)) {
			ccbs::user_error(_("There aren't any songs left in the song selector!"));
		}
		$dbh->do('INSERT INTO randomsongsused (song) VALUES (?)',
			undef, $ref->{'song'});
		$dbh->do('INSERT INTO roundrandomsongs (tournament, round, parallel, song) VALUES (?,?,?,?)',
			undef, $tournament, $round, $gg, $ref->{'song'});

		$dbh->do('INSERT INTO scores SELECT tournament,round,parallel,player,?,?,\'single\',\'expert\',\'f\',NULL FROM roundparticipation WHERE tournament=? AND round=? AND parallel=?', undef,
			$s, $ref->{'song'}, $tournament, $round, $gg);
	}
}

# Add empty "score" records for the chosen songs.
for my $g (1..$num_groups) {
	my $gg = ($num_groups == 1) ? 0 : $g;

	for my $s (1..$num_chosen) {
		$dbh->do('INSERT INTO scores SELECT tournament,round,parallel,player,?,NULL,\'single\',\'expert\',\'t\',NULL FROM roundparticipation WHERE tournament=? AND round=? AND parallel=?', undef,
			$s + $num_random, $tournament, $round, $gg);
	}
}

ccbs::print_see_other('show-tournament.pl?id=' . $tournament);

$dbh->commit;
$dbh->disconnect;
