#!perl -w

# Copyright (C) 1997 Capella Computers Ltd.
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
# 
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
# 
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.

# :FILE:
# List all jobs (with optional filtering by status or user).

use strict;
use English;
use P4;

# Mask of status and users to print.
my %status_mask;
my %user_mask;

# Set mask for status.
sub set_status {
    my $status = shift;			# Status to set ('Status' for all).
    my $to = shift;			# What to set it to.

    if ($status =~ /^n|new/i) {
	$status_mask{new} = $to;
    } elsif ($status =~ /^w|work/i) {
	$status_mask{work} = $to;
    } elsif ($status =~ /^r|review/i) {
	$status_mask{review} = $to;
    } elsif ($status =~ /^i|integ/i) {
	$status_mask{integ} = $to;
    } elsif ($status =~ /^f|fail/i) {
	$status_mask{fail} = $to;
    } elsif ($status =~ /^p|pass/i) {
	$status_mask{pass} = $to;
    } elsif ($status =~ /^c|clear/i) {
	$status_mask{clear} = $to;
    } elsif ($status =~ /^d|done/i) {
	$status_mask{done} = $to;
    } elsif ($status eq '_') {
	$status_mask{'_new'} = $to;
	$status_mask{'_work'} = $to;
	$status_mask{'_review'} = $to;
	$status_mask{'_integ'} = $to;
	$status_mask{'_fail'} = $to;
	$status_mask{'_pass'} = $to;
	$status_mask{'_clear'} = $to;
	$status_mask{'_done'} = $to;
    } elsif ($status =~ /^s|status/i) {
	$status_mask{new} = $to;
	$status_mask{work} = $to;
	$status_mask{review} = $to;
	$status_mask{integ} = $to;
	$status_mask{fail} = $to;
	$status_mask{pass} = $to;
	$status_mask{clear} = $to;
	$status_mask{done} = $to;
	$status_mask{'_new'} = $to;
	$status_mask{'_work'} = $to;
	$status_mask{'_review'} = $to;
	$status_mask{'_integ'} = $to;
	$status_mask{'_fail'} = $to;
	$status_mask{'_pass'} = $to;
	$status_mask{'_clear'} = $to;
	$status_mask{'_done'} = $to;
    } else {
    	P4::crash("Specified status should be one of: Status (all), ",
	    "_ (All), New, Work, Review, Fail, Pass, Integ, Clear or Done.");
    }

    # Be nice.
    return 1;
}

# Set mask for a user.
sub set_user {
    my $user = shift;			# User to set it to ('User' for all).
    my $to = shift;			# What to set it to.

    if ($user =~ /u|user/i) {
	%user_mask = ( 'default' => $to );
    } elsif ($user =~ /m|me/i) {
	$user_mask{P4::current_user()} = $to;
    } else {
	$user_mask{$user} = $to;
    }

    # Be nice.
    return 1;
}

# By default, print all.
set_status('Status', 1);
set_user('User', 1);

# These are used to reverse the default if first option is with a '+'.
my $first_status = 1;
my $first_user = 1;

# Command line argument specify which status jobs to print.
my $opt;
while ($opt = shift(@ARGV)) {

    # +u turns on a specific user.
    if ($opt eq '+u' || $opt eq '+U') {

	# If the first user-related command is +u,
	# no user will be printed by default.
	if ($first_user) {
	    set_user('User', 0);
	    $first_user = 0;
	}

	$opt = shift(@ARGV);
	defined($opt)
	    || P4::crash("+u flag requires an argument.");
	set_user($opt, 1);

    # -u turns off a specific user.
    } elsif ($opt eq '-u' || $opt eq '-U') {
	$opt = shift(@ARGV);
	defined($opt)
	    || P4::crash("+u flag requires an argument.");
	set_user($opt, 0);

    # -X turns off a specific status.
    } elsif ($opt =~ /^-(.*)/) {
	set_status($1, 0);

    # +X turns on a specific status.
    } elsif($opt =~ /^\+(.*)/) {

	# If the first status related command -s +X,
	# no status will be printed by default.
	if ($first_status) {
	    set_status('Status', 0);
	    $first_user = 0;
	}

	set_status($1, 1);

    } else {
    	# Whoever can understand this usage probably doesn't need it :-)
	P4::crash("Usage: p4jl ",
	    "[{ {+/-}{Status|New|Work|Review|Fail|Pass|Integ|Clear} | ",
	    "{+/-}u {User|Me|<user-name>} } ...]");
    }
}

# No need to lock since this is a harmless read-only operation.

# Obtain full list of jobs.
my %jobs = P4::jobs();

# Print column titles.
print "Job\tCreated     Re\tUser\tReview\tStatus\tTitle\n";
print "---\t----------  --\t----\t------\t------\t-----\n";

# Print all jobs, sorted by reversed ID (more recent first).
my $job;
foreach $job (reverse(sort(keys(%jobs)))) {

	# Parse record.
	my $record = $jobs{$job};
	my $user = $record->{user};
	my $created = $record->{created};
	my $status = $record->{status};
	my $retry = $record->{retry};
	my $reviewer = $record->{reviewer};
	my $version = $record->{version};
	my $title = $record->{title};

	# Filter out undesired jobs.
	next if !$status_mask{$status};
	if (defined($user_mask{$user})) {
	    next if !$user_mask{$user};
	} else {
	    next if !$user_mask{default};
	}

	# This saves a column.
	if ($status eq 'done') {
	    $status = $version;
	}

	# Print it nicely.
	print $job, "\t";
	print $created, '  ';
	print $retry, "\t";
	print $user, "\t";
	print $reviewer, "\t";
	print $status, "\t";
	print $title, "\n";
}

# Be nice.
1;