#!/usr/local/vol/perl/5.0044/bin/perl -w

use strict;
use News::NNTPClient;
use News::Newsrc;
use Env qw(HOME);
use File::Basename;
use Getopt::Long;
use Set::IntSpan;

my $verbose = 0;
my $reportnounread = 0;
my $count = 0;
my $catchup = 0;
my $newsrcfile = $HOME.'/.newsrc';
my $newshost    = 'news.kth.se';    
my $newsport    = '119';
my $progname = (fileparse($0, ''))[0];
my @exclude;
my @only;

sub showhelp {
    print "\n";
    print "NAME\n";
    print "\n";
    print "  $progname - checks for unread messages in newsgroups\n";
    print "\n";
    print "SYNOPSIS\n";
    print "\n";
    print "  $progname [--help | --version]\n";
    print "\n";
    print "  $progname [--verbose | --catchup] [--reportnounread] [--file=filename] \n";
    print "         [--only=newsgroup | --exclude=newsgroup] \n";
    print "         [--host=hostname] [--port=portnumber]\n";
    print "\n";
    print "  The $progname program handles the .newsrc-file and checks for unread \n";
    print "  messages.\n";
    print "\n";
    print "FLAGS\n";
    print "\n";
    print "  --help     Show this screen.\n";
    print "\n";
    print "  --version  Show the version number and exit.\n";
    print "\n";
    print "  --verbose  Outputs the amount of unread articles in each group which \n";
    print "             have unread messages. If the user has subscribed to many\n";
    print "             very large groups (>10000 messages) this operation may be\n";
    print "             slow due to the set operations performed. Not recommended.\n";
    print "\n";
    print "  --catchup  Catches up on all articles in all subscribed groups. That is\n";
    print "             sets the newsrc so that there no longer are any unread articles. \n";
    print "\n";
    print "  --reportnounread  If verbose mode is not enabled, this switch will output\n";
    print "             the message 'You have no unread news.' if there were no unread\n";
    print "             articles. Otherwise $progname is quiet and will not say anything.\n";
    print "\n";
    print "  --only     Doesn't look for subscribed groups in the newsrc-file, instead the\n";
    print "             groups specified on the commandline is used. Multiple --only can\n";
    print "             be used to specify any number of groups to check. Cannot be\n";
    print "             used in combination with --exclude.\n";
    print "\n";
    print "  --exclude  Removes the specified groups from the subscribed groups in the \n";
    print "             newsrc-file. Multiple --exclude can be used to remove any number\n";
    print "             of groups. Cannot be used in combination with --only.\n";
    print "\n";
    print "  --file     Uses another file instead of .newsrc. The whole path must be\n"; 
    print "             supplied.\n";
    print "\n";
    print "  --host     Uses another newshost instead of the default ($newshost)\n";
    print "\n";
    print "  --port     Uses another newsport instead of the default ($newsport)\n";
    print "\n";
    print "ENVIRONMENT VARIABLES\n";
    print "\n";
    print "  The following environment variables affect the execution of $progname:\n";
    print "\n";
    print "  HOME     Provides a default value users home directory and where to find\n";
    print "           the .newsrc-file.\n";
    print "\n";
    print "NOTES\n";
    print "\n";
    print "  The options may be given with double dashes instead of single dashes and\n";
    print "  the equalsigns may be omitted. Also the options may be invoked with unique\n";
    print "  abbreviations.\n";
    print "\n";
    print "REQUIREMENTS\n";
    print "\n";
    print "  Perl 5 with the modules NNTPClient and News-Newsrc.\n";
    print "\n";
    print "KNOWN BUGS\n";
    print "\n";
    print "  Eats a lot of memory and CPU, especially if the user is subscribed to large\n";
    print "  newsgroups with a lot of messages. This will probably not be fixed :-)\n";
    print "\n";
    print "  Anyway, tin, slrn and knews are much faster at this operation and should be\n";
    print "  used instead.\n";
    print "\n";
    print "AUTHOR\n";
    print "\n";
    print "  Max Zomborszki <max\@e.kth.se>\n";
    print "\n";
    exit;
}

sub showversion {
    print " $progname version 0.2\n";
    exit;
}

GetOptions("h" => \&showhelp, 
	   "help" => \&showhelp,
	   "version" => \&showversion,
	   "exclude=s" => \@exclude,
	   "only=s" => \@only,
	   "verbose" => \$verbose,
	   "reportnounread" => \$reportnounread,
	   "catchup" => \$catchup,
	   "file=s" => \$newsrcfile,
	   "host=s" => \$newshost,
	   "port=s" => \$newsport);

die "error: --exclude and --only are mutually exclusive.\n" if (defined @exclude and defined @only);
die "error: --verbose and --catchup are mutually exclusive.\n" if ($verbose + $catchup > 1);

my $newsrc = News::Newsrc->new();
my $client = new News::NNTPClient($newshost, $newsport);
die "\nCould not contact $newshost:$newsport\n" unless($client->ok);

my ($group,         # The current group
    @chkgroups,     # List of groups to check for unread news..
    %groups);       # The number of unread articles in each group.

die "error: could not open $newsrcfile for reading\n" unless $newsrc->load($newsrcfile);
if (defined @only) {
    @chkgroups = @only;
} else {
    @chkgroups = $newsrc->sub_groups;
    if (defined @exclude) {
	# För alla er som tycker perl är krångligt så betyder denna rad
	# att man tar bort alla förekomster av element i @exclude ur 
	# arrayen @chkgroups.
	@chkgroups = grep {my $x = $_; !grep /$x/, @exclude} @chkgroups;
    }
}

if($catchup) {
    foreach $group (@chkgroups) {
	my @allartarr = $client->listgroup($group);
	$newsrc->mark_list($group, \@allartarr);
    }
    $newsrc->save();
} elsif($verbose) {
    foreach $group (@chkgroups) {
	my @allartarr = $client->listgroup($group);
	my $allartset = new Set::IntSpan \@allartarr;
	my @readartarr = $newsrc->marked_articles($group);
	my $readartset = new Set::IntSpan \@readartarr;
	my $unreadartset = diff $allartset $readartset;
	my @unreadartarr = elements $unreadartset;
	$groups{$group} = scalar @unreadartarr if (scalar @unreadartarr);
    }

    if (scalar keys %groups) {
	foreach $group (sort keys %groups) {
	    printf("%8d : %-40s\n", $groups{$group}, $group);
	}
	exit 1; # Or what should I have here?
    } else {
	print "You have no unread news.\n";
    }
} else {
    foreach $group (@chkgroups) {
	my @allartarr = $client->listgroup($group);
	my $allartset = new Set::IntSpan \@allartarr;
	my @readartarr = $newsrc->marked_articles($group);
	my $readartset = new Set::IntSpan \@readartarr;
	my $unreadartset = diff $allartset $readartset;
	my @unreadartarr = elements $unreadartset;
	if (scalar @unreadartarr) {
	    print "You have unread news.\n";
	    exit 1;             # Or what should I have here?
	}
    }
    print "You have no unread news.\n" if $reportnounread;
}


