#!/usr/bin/perl

use strict ;
use warnings ;
use autodie ;

use Time::Local ;
use IPC::Run ;

my $type = $ARGV[0] ;
my $name = $ARGV[1] ;
my $file = $ARGV[2] ;

my $DEBUG = 0 ;

if (!$type) {
    fail('missing wallet type') ;
}

if (!$name) {
    fail('missing wallet name') ;
}

if (!$file) {
    fail('missing file name') ;
}

# Make sure that either the file does not exist, or if it _does_ exist, is
# a regular file.
if ((-e $file) && (!(-f $file))) {
    fail("the file '$file' exists but is not a regular file") ;
}

# Get the wallet object's metadata (i.e., its last stored date).
my $wallet_last_stored_epoch = wallet_last_stored_epoch($type, $name) ;

# Does the wallet object exist? If not, die.
if (!$wallet_last_stored_epoch) {
    fail("wallet object '$type' with name '$name' does not exist") ;
}

# Get the file's last changed date
my $file_last_change_epoch = get_file_last_change($file) ;

if ($file_last_change_epoch < $wallet_last_stored_epoch) {
    progress('returning 0') ;
    exit(0) ;
} else {
    progress('returning 1') ;
    exit(1) ;
}

sub wallet_last_stored_epoch {
    my ($wallet_type, $wallet_name) = @_ ;

    my @command = (
      'wallet',
      'show',
      $wallet_type,
      $wallet_name,
    ) ;

    my ($out, $err) ;
    progress(q{about to run command '} . join(q{ }, @command) . q{'}) ;

    IPC::Run::run(\@command, q{>}, \$out, q{2>}, \$err) ;
    my $rv = $? >> 8 ;

    if ($err) {
        fail("'wallet_last_stored_epoch' failed: $err") ;
    }

    progress('result of wallet command run:') ;
    progress("stdout: $out") ;
    progress("stderr: $err") ;
    progress("exit value: $rv") ;

                # Stored on: 2014-01-06 16:16:41
    if ($out =~ m{Stored on: (\d\d\d\d)-(\d\d)-(\d\d) (\d\d):(\d\d):(\d\d)}) {
        my $year = $1 ;
        my $mon  = $2 ;
        my $mday = $3 ;
        my $hour = $4 ;
        my $min  = $5 ;
        my $sec  = $3 ;

        # Convert to epoch
        my $epoch = timelocal($sec, $min, $hour, $mday, $mon, $year) ;
        progress("epoch time for wallet object: $epoch") ;

        return $epoch ;

    } else {
        fail("could not parse wallet metadata string '$out'") ;
    }

    return ;
}

sub get_file_last_change {
    my ($filepath) = @_ ;

    if (!(-e $filepath)) {
        progress('epoch time for file:          -1') ;
        return -1 ;
    } else {
        my $epoch = (stat($filepath))[9] ;
        progress("epoch time for file:          $epoch") ;
        return $epoch ;
    }
}

sub progress {
    my ($msg) = @_ ;

    if ($DEBUG) {
        print $msg . "\n" ;
    }
    return ;
}

sub fail {
    my ($msg) = @_ ;

    $msg =~ s{^\s*}{}g ;
    $msg =~ s{\s*$}{}g ;

    print $msg . "\n" ;
    exit(255) ;
}

__END__

#############################################################################

#   wallet-object-is-newer <wallet_type> <wallet_name> <file>
#
#   Returns 0 if the wallet object is newer than the file

#


=head1 NAME

    wallet-object-is-newer - Compare a wallet object and a file

=head1 SYNOPSIS

    wallet-object-is-newer <wallet_type> <wallet_name> <file>

=head1 DESCRIPTION

Compare the "Stored on" date of the wallet object with name C<wallet_name>
and type C<wallet_type> with the last-modified date of C<file>. Exits
successfully (value 0) if the wallet object is newer than the file.

Exits with value 255 in the following cases:
=over
=item The wallet type not supplied.
=item The wallet type is not "file".
=item The wallet name not supplied.
=item The wallet object does not exist or is not accessible.
=item The wallet object does not have a last stored date.
=item The file name is not supplied.
=item The file name is supplied AND exists AND is not a regular file.
=back

Exits with value 0 in the following cases:
=over
=item The wallet object exists AND the file does not exist.
=item The wallet object exists AND the file exists AND the file
object is a regular file AND the file object has a last
modified date STRICTLY LESS THAN the wallet object's stored-on
date.
=back

Exits with value 1 in the following cases:
=over
=item The wallet object exists AND the file exists AND the file
is a regular file AND the file has a last-modified date GREATER THAN OR
EQUAL TO the wallet object's stored-on date.
=back

=head1 NOTE

Currently, the only wallet type supported is "file". Any other wallet type
supplied results in an exit value of 255.

=head1 AUTHOR

Adam Lewenberg <adamhl@stanford.edu>

=head1 COPYRIGHT AND LICENSE

Copyright 2014 The Board of Trustees of the Leland Stanford Junior
University.  All rights reserved.

Permission to use, copy, modify, and distribute this software and its
documentation for any purpose and without fee is hereby granted, provided
that the above copyright notice appear in all copies and that both that
copyright notice and this permission notice appear in supporting
documentation, and that the name of Stanford University not be used in
advertising or publicity pertaining to distribution of the software
without specific, written prior permission.  Stanford University makes no
representations about the suitability of this software for any purpose.
It is provided "as is" without express or implied warranty.

THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.

=cut

#############################################################################
