#!/usr/bin/perl

# Format of data files is as follows:
# line 1: target value names each separated by a space
# line 2: # of total words for all documents in each target value each
#         separated by a space
# line 3: number of documents for each category
# line 4: a vocab word, followed by pairs of category numbers and the word
#         frequency for that category

# When a vocab word is refiled it is assumed that this is the desired
#      target value (or folder, in this case).

# tv = target value


# This program accepts a document from standard input and files in into
#   the mailbox which it deems most apporpriate, using the information
#   found in ~/.idata (data obtained from previous refilings).

open(TMP, ">> /tmp/ifilter.info")
    || print "Can't open /tmp/ifilter.info: $!\n";

print TMP "ifilter called ";
print TMP "(@ARGV)\n";


$home_dir = $ENV{"HOME"}."/";

open(MH, "< $home_dir.mh_profile");

while (<MH>) {
    if (m/Path: (\w+)/) {
	$mail_path = $1;
	$mail_path .= "/";
    }
    if (m/draft-folder: (\w+)/) {
	$draft_folder = $1;
    }
}

# updates accuracies file ~/.idata_accuracy

$acc_file = $home_dir.".idata_accuracy";

$filters = 1;
$refiles = 0;

if (open(ACC, $acc_file))
{
    $line = <ACC>;
    $line =~ m/filters\s*=\s*(\d*)\s*refiles\s*=\s*(\d*)/;

    $filters += $1;
    $refiles += $2;

    $accuracy = int(($filters - $refiles)/$filters * 10000)/100;
    print TMP "filters = $filters  refiles = $refiles\n";
    print TMP "Accuracy = $accuracy \%\n";

    close(ACC);
}

if (open(ACC, "> $acc_file"))
{
    print ACC "filters = $filters  refiles = $refiles\n";
    if ($accuracy) { print ACC "Accuracy = $accuracy \%\n"; }
    close(ACC);
} else {
    print TMP "Was not able to write accuracies file\n";
}

$tot_words = 0;

# target values and 'n' both start with index 1
$tv[0] = 0;

$data_file = $home_dir.".idata";

if (open(DATA, "< $data_file")) 
{
    # reads in category names
    $line = <DATA>;
    while ($line =~ s/(\S+)\s+//)
    {
	$tv[$#tv+1] = $1;
    }

    # reads in total number of words for each category
    $line = <DATA>;
    $i = 1;
    while ($line =~ s/(\d+)\s+//) 
    {
	$n{$tv[$i++]} = $1;
    }
    if ($i <= $#tv) { &ouch("Bad data file format - line #2"); }

    # reads in number of documents for each category
    $line = <DATA>;
    $i = 1;
    while ($line =~ s/(\d+)\s+//)
    {
	$docs{$tv[$i++]} = $1;
	$tot_docs += $1;
    }
    if ($i <= $#tv) { &ouch("Bad data file format - line #3"); }
    
    # reads in actual word frequencies
    $word[0] = "";

    while (($line = <DATA>) && (!($line =~ m/^\s*$/)))  {
	$tot_words++;

	# reads word
	$line =~ s/^(\w+)\s+// || &ouch("Couldn't read vocab word");
	$word[$#word+1] = $1;
	$index{$1} = $#word;

	# reads age of word
	$line =~ s/^(\d+)\s+// || &ouch("Couldn't read age of word");
	$age{$word[$#word]} = $1;

	if ($word[$#word] eq "afs") { print "afs "; }

	# reads in frequency per category   cat_num:freq
	while ($line =~ s/(\d+):(\d+)\s+//) 
	{
	    $nk{$word[$#word].",".$tv[$1]} = $2;

	    if ($word[$#word] eq "afs") {
		print "$tv[$1] = $2  ";
	    }
 	}
	if ($word[$#word] eq "afs") { print "\n"; }
	if (!($line =~ m/^\s*$/)) { &ouch("Vocab line # $tot_words has bad format"); }
    }
} else {

    @lines = <STDIN>;

    &rcvstore(inbox);

    exit 0;
}

close(DATA);

$best_rating = 0;
$best_target = 0;

@lines = <STDIN>;

for ($i=1; $i <= $#tv; $i++) 
{
    $target_rating = 0;
    for ($j=0; $j <= $#lines; $j++) 
    {
	$line = $lines[$j];
	while ($line =~ s/([A-Za-z]+)[^A-Za-z]+//)
	{
	    $wrd = $1;

	    # get rid of tiny words
	    if (length($wrd) > 2) 
	    {
		$wrd =~ tr/A-Z/a-z/;
		
		$target_rating += log(($nk{$wrd.",".$tv[$i]} + 1) /
				      ($n{$tv[$i]} + $tot_words));
	    }
	}
    }
    
    print TMP "$tv[$i] given rating of $target_rating\n";

    $target_rating += log(($docs{$tv[$i]} + 1) / ($tot_docs + $#tv));

    if (($target_rating > $best_rating) || ($best_target == 0)) {
	$best_rating = $target_rating;
	$best_target = $i;
    }
}

print TMP "Filed message in $tv[$best_target] ($best_target)\n";

print TMP "\n";
close(TMP);

rcvstore($tv[$best_target]);

exit 0;

# rcvstore function expects lines of input file to be stored in @lines - bad
#   assumption, I know.  I'll fix it later.  Really :)

sub rcvstore {
    local($mailbox) = @_;

    print TMP "Filed to $mailbox\n";
    
    open(RCV, "| /usr/lib/mh/rcvstore +$mailbox") || die "could not rcvstore\n";
    
    foreach $line (@lines) {
	print RCV $line;
    }
    
    close(RCV);
}


sub ouch {
    local($string) = @_;
    print TMP $string;
    die $string.": $!\n";
}
