#!/usr/bin/perl

# A little command-line interface for manipulating
# debbugs .log files.

# Copyright (C) 2003 Thomas Roessler <roessler@does-not-exist.org>

# GPLed.

# use lib '/var/lib/debbugs/tools/debbugs';  # XXXXX
use lib './debbugs';

use Term::ReadLine;
use Debbugs::Log;

my $term = new Term::ReadLine 'Debbugs Command Line Interface';
my $prompt = "debbugs> ";

my $OUT = $term->OUT || \*STDOUT;

my @entries  = ();
my $filename = undef;

$SIG{PIPE} = "IGNORE";

print $OUT "Debbugs Command Line Interface\n";
print $OUT "Copyright (c) 2003 Thomas Roessler <roessler@does-not-exist.org>\n";
print $OUT "GPLed.\n";

L: while ( defined($_ = $term->readline ($prompt))) {
    $term->addhistory ($_);
    if (/^\s*\?\s*$/i) {
	print $OUT "<n>          \tDisplay record.\n";
	print $OUT "h [<n>[-<m>]]\tDisplay summary information.\n";
	print $OUT "d <n>[-<m>]  \tDelete records.\n";
	print $OUT "u <n>[-<m>]  \tUndelete records.\n";
	print $OUT "\n";
	print $OUT "o <f>        \tOpen file.\n";
	print $OUT "c            \tCommit changes.\n";
	print $OUT "w <f>        \tWrite file.\n";
	print $OUT "q            \tquit\n";
    } elsif (/^\s*([hi])\s*$/i) {
	eval {
	    open PAGER, "|more" || die "Can't start pager.";
	    display_headers (\*PAGER, \@entries, -1, -1, $1);
	    close PAGER;
	};
	if ($@) {
	    print $OUT, $@;
	}
    } elsif (/^\s*[hi]\s*([0-9]+)\s*$/i) {
	if ($1 > $#entries) {
	    print OUT "No such entry.\n";
	} else {
	    display_header ($OUT, \@entries, $1);
	}
    } elsif (/^\s*([hi])\s*([0-9]+)\s*-\s*([0-9]*)\s*$/i) {
	eval {
	    my $a = $2;
	    my $b = $3;
	    my $op = $1;
	    
	    $b = $#entries if (!$b && $a);
	    
	    open PAGER, "|more" || die "Can't start pager.";
	    display_headers (\*PAGER, \@entries, $a, $b, $op);
	    close PAGER;
	};
	if ($@) {
	    print $OUT, $@;
	}
    } elsif (/^\s*([0-9]+)\s*$/i) {
	if ($1 > $#entries) {
	    print $OUT "No such entry.\n";
	} else {
	    display_entry ($OUT, $entries[$1]);
	}
    } elsif (/^\s*([du])\s*([0-9]+)\s*$/i) {
	my $i = $2;
	my $o = $1;

	$o = 1 if ($1 =~ /d/i);
	$o = 0 if ($1 =~ /u/i);
	
	if ($i > $#entries) {
	    print $OUT "No such entry.\n";
	} else {
	    $entries[$i]->{delete} = $o;
	}
    } elsif (/^\s*([du])\s*([0-9]+)\s*-\s*([0-9]*)\s*$/i) {
	my $a = $2;
	my $b = $3;
	my $o = $1;

	$b = $#entries if (!$b && $a);
	
	$o = 1 if ($o =~ /d/i);
	$o = 0 if ($o =~ /u/i);
	
	for my $i ($a .. $b) {
	    if ($i > $#entries) {
		# print $OUT "$i: No such entry.\n";
	    } else {
		$entries[$i]->{delete} = $o;
	    }
	}
    } elsif (/^\s*o\s+(.*?)\s*$/i) {
	eval {
	    open INPUT, $1 || die "Can't open $1";
	    @entries = read_log_records (\*INPUT);
	    close (INPUT);
	    $prompt = $1 . "/" . $#entries . "> ";
	};
	if ($@) {
	    print $OUT $@;
	    @entries = ();
	    $prompt = "debbugs> ";
	}
    } elsif (/^\s*c\s*$/i) {
	my $i;
	for ($i = 0; $i <= $#entries; $i++) {
	    if ($entries[$i]->{delete}) {
		splice @entries, $i, 1;
		$i--;
	    }
	}
    } elsif (/^\s*w\s+(.*?)\s*$/i) {
	eval {
	    open OUTPUT, ">$1" || die "Can't open $1";
	    write_log_records (\*OUTPUT, @entries);
	    close OUTPUT || die "Can't close $1";
	};
	if ($@) {
	    print $OUT $@;
	}	    
    } elsif (/^\s*\/(.*?)\s*$/i) {
	my $r = qr ($1);
	for my $e (0 .. $#entries) {
	    if ($entries[$e]->{text} =~ $r) {
		$entries[$e]->{matches_search} = 1;
		display_header ($OUT, \@entries, $e);
	    } else {
		$entries[$e]->{matches_search} = 0;
	    }
	}
    } elsif (/^\s*q\s*$/i) {
	last L;
    } else {
	print $OUT "I don't understand that.\n";
    }
}

sub display_header {
    my $out = shift;
    my $es = shift;
    my $e = shift;

    printf $out "%5d %1s%1s  %s\n",
      $e,
      ${$es}[$e]->{delete} ? "d" : " ",
      ${$es}[$e]->{matches_search} ? "/" : " ",
      ${$es}[$e]->{type};
}

sub display_headers {
    my $out = shift;
    my $es  = shift;
    my $a   = shift;
    my $b   = shift;
    my $op  = shift;
    
    $a = 0 		if $a == -1;
    $b = $#{$es} 	if $b == -1;

    for my $i ($a .. $b) {
	if ($i > $#{$es}) {
	    # print $OUT "$i: No such entry.\n";
	} else {
	    if (($op =~ /h/i) || ($entries[$i]->{type} =~ /incoming-recv/i)) {
		display_header (\*PAGER, $es, $i);
	    }
	}
    }
}

sub display_entry {
    my $out = shift;
    my $e   = shift;
    
    eval {
	open PAGER, "|more";
	print PAGER $e->{text};
	close PAGER;
    };

    if ($@) {
	print $out $@;
    }
}
