#!/usr/bin/perl

use strict;
use warnings;

use CUPS::Spool;
use Data::Dumper;
use File::Basename;
use POSIX qw( strftime );

my( $SPOOL, @LIST, %FIELDS, $SHELL );
$SPOOL = CUPS::Spool->new;
my $argc = 0+@ARGV;
if( $argc ) {
    while( @ARGV ) {
        my $file = shift;
        if( -d $file ) {
            $SPOOL = CUPS::Spool->new( { dir => $file } );
            unless( -r $file ) {
                warn "$file: $!\n";
                next;
            }
            if( 1==$argc ) {
                push @LIST, map { $SPOOL->control_file( $_ ) } $SPOOL->list 
            }
        }
        elsif( $file =~ /^\d+$/ ) {
            push @LIST, $SPOOL->control_file( $file );
        }
        elsif( -f $file and $file =~ /(\d+)$/ ) {
            push @LIST, $file;
        }
        elsif( $file eq '-f' or $file eq '--field' ) {
            $argc-=2;
            foreach my $v ( split /\s*,\s*/, shift ) {
                $FIELDS{ $v }++;
            }
        }
        elsif( $file eq '-s' or $file eq '--sh' ) {
            $argc--;
            $SHELL=1;
        }
        elsif( $file eq '-h' or $file eq '--help' ) {
            usage();
            exit 0;
        }
        else {
            warn "Ignoring $file\n";
        }
    }
}
if( $argc == 0 ) {
    @LIST = map { $SPOOL->control_file( $_ ) } $SPOOL->list;
    if( $! ) {
        warn "$!\n";
    }
}

################################################
foreach my $file ( @LIST ) {
    $file =~ /(\d+)$/;
    my $num = 0+$1;

    # load
    unless( -f $file and -r $file ) {
        warn "Unable to locate $file: $!\n";
        next;
    }
    my $job = $SPOOL->load( $file );

    # control file
    unless( %FIELDS and not $FIELDS{control} ) {
        print_str( $num, control => $job->control_file );
    }
    # data files
    unless( %FIELDS and not $FIELDS{data} ) {
        print_array( $num, 'data', [ $job->data_files ] );
    }

    # attributes
    foreach my $A ( $job->attr ) {
        my $name = $A->name;
        my $v = $A->value;
        if( not %FIELDS or $FIELDS{ $name } ) {
            my $r = ref $v;
            if( $name =~ /^time-/ and $v) {
                $v = strftime "%Y-%m-%d %H:%M:%S", localtime $v;
            }
            unless( $r ) {
                print_str( $num, $name, $v );
            }
            elsif( 'ARRAY' eq $r ) {
                print_array( $num, $name, $v );
            }
            elsif( 'HASH' eq $r ) {
                print_hash( $num, $name, $v );
            }
        }
        if( not %FIELDS or $FIELDS{ "$name.cooked" } ) {
            if( $name eq 'job-state' ) {
                foreach my $state ( qw( PENDING HELD PROCESSING STOPPED 
                                        CANCELLED ABORTED COMPLETED ) ) {
                    next unless $job->$state;
                    print_str( $num, "$name.cooked", $state );
                }
            }
        }
    }            

    print "\n" if $file ne $LIST[-1] and not %FIELDS;
}

################################################
sub print_str
{
    my( $num, $prefix, $str ) = @_;
    if( $SHELL ) {
        $prefix =~ s/\./_/g;
        print qq(JOB_${num}_$prefix="$str"\n);
    }
    else {
        print "$num.$prefix: $str\n";
    }
}

################################################
sub print_array
{
    my( $num, $prefix, $LIST ) = @_;
    my $n = 1;
    foreach my $v ( @$LIST ) {
        print_str( $num, "$prefix.$n", $v );
        $n++;
    }
}

################################################
sub print_hash
{
    my( $num, $prefix, $LIST ) = @_;
    foreach my $k ( keys %$LIST ) {
        print_str( $num, "$prefix.$k", $LIST->{$k} );
    }
}


################################################
sub usage
{
    my $file = basename $0;
    print <<TXT;
Usage: 
    $file [OPTION] SPOOL | NUM | FILE

Options:
    -f, --field FIELD1,FIELD2
        Only show FIELD1, FIELD2 etc
    -s, --sh
        Output shell variables
    -h, --help
        This help
TXT

}