#!/usr/bin/perl -w
use strict;

if (@ARGV != 2) {
    print STDERR "Usage: genutts.pl <GF grammar> <number of utterances>\n";
    exit 2;
}

my ($gf_grammar,$num) = @ARGV;

if (! -f $gf_grammar) {
    print STDERR "GF grammar '$gf_grammar' not found\n";
    exit 2;
}

print STDERR "Getting list of all words in the grammar...\n";

my @words = allwords($gf_grammar);

print STDERR "Number of unique words in grammar: " . @words . "\n";

my $n = 2 * $num;

print STDERR "Generating $n utterances...\n";

my @utts = generate_random($gf_grammar, $n);

print STDERR "Removing duplicates...\n";

# Keep unique utterances only
@utts = scramble(uniq(sort(@utts)));

print STDERR "Number of unique utterances: " . @utts . "\n";

# Cap the number of utterances
@utts = @utts >= $num ? @utts[0..$num-1] : @utts;

print STDERR "Keeping " . @utts . " utterances.\n";

my %counts = count_words(@utts);

my @unused_words = ();
foreach (@words) {
    if (!defined $counts{$_}) {
	push @unused_words, $_;
    }
}

print STDERR "Number of unique words in generated utterances: " . keys(%counts) . "\n";

print STDERR "Number of grammar words not in generated utterances: " . @unused_words . "\n";

#if (@unused_words > 0) {
#    print STDERR "Grammar words not in generated utterances:\n";
#    print STDERR join(", ", @unused_words) . "\n";
#}

print STDERR "\n";

#print STDERR "Grammar words:\n";
#foreach (@words) {
#    print STDERR "$_\n";
#}

print STDERR "Word counts:\n";
foreach (sort({$counts{$b} <=> $counts{$a}} keys(%counts))) {
    print STDERR sprintf("%5d %s\n",$counts{$_},$_);
}





my $name = 0;
foreach my $u (@utts) {
    printf("%06d: $u\n", $name);
    $name++;
}




sub scramble {
    for (my $i = 0; $i < @_; $i++) {
	my $j = int(rand(@_));
	my $t = $_[$i];
	$_[$i] = $_[$j];
	$_[$j] = $t;
    }
    return @_;
}

sub uniq {
    my $prev = undef;
    my @r = ();
    foreach my $x (@_) {
	if (!defined $prev || $x ne $prev) {
	    push @r, $x;
	    $prev = $x;
	}
    }
    return @r;
}

sub allwords {
    my $grammar = $_[0];

    my @r = ();

    open GF, "echo 'pg -printer=fullform' | gf -s -batch -nocpu '$grammar' |";
    while (<GF>) {
	if (!/^\s*$/) {
	    chomp;
	    s/([^:]*)\s:.*/$1/;
	    push @r, $_;
	}
    }
    close GF;

    return @r;
}

sub generate_random {
    my ($grammar, $n) = @_;

    my @r = ();

    open GF, "echo 'gr -number=$n | l' | gf -s -batch -nocpu '$grammar' |";
    while (<GF>) {
	if (!/^\s*$/) {
	    chomp;
	    push @r, $_;
	}
    }
    close GF;

    return @r;
}

sub count_words {
    my %r = ();
    
    foreach (@_) {
	foreach (split) {
	    my $x = $r{$_};
	    if (!defined $x) {
		$x = 0;
	    }
	    $r{$_} = $x+1;
	}
    }

    return %r;
}

