#!/usr/bin/perl -w
#
# ecaccess-file-get: Download an ECaccess File
#
# Laurent.Gougeon@ecmwf.int - 2010-10-15

use ECMWF::ECaccess;
use Getopt::Long;
use Pod::Usage;
use MIME::Base64;

my %opt = ( progress => 0, offset => 0, bufsize => 1048576, version => 0, help => 0, manual => 0, debug => 0 );

pod2usage( -noperldoc => 1, -exit => 1, verbose => 1 ) if !GetOptions(
	\%opt,
	qw(
	  progress
	  offset=i
	  bufsize=i
	  version
	  help|?
	  manual
	  debug
	  )
);

# Display version if requested
die ECMWF::ECaccess->VERSION . "\n" if ( $opt{version} );

my $sourceECaccessFile = $ARGV[0];
my $targetLocalFile    = $ARGV[1];

pod2usage( -noperldoc => 1, -exit => 1, verbose => 1 ) if ( $opt{help} );
pod2usage( -noperldoc => 1, -exit => 1, verbose => 2 ) if ( $opt{manual} );
pod2usage( -noperldoc => 1, -exit => 1, verbose => 0, -msg => "No source-ecaccess-file specified!\n" ) if not($sourceECaccessFile);

# Create the ECaccess Controler
my $ecaccess = ECMWF::ECaccess->new();
$ecaccess->setDebug( $opt{debug} );

# Get the Token (using the Certificate in $HOME)
my $token = $ecaccess->getToken();

# Get the Control Channel
my $controlChannel = $ecaccess->getControlChannel();

# Get the details of the remote file
my @files = $controlChannel->getDirList( $token, $sourceECaccessFile, 'false' )->valueof('//getDirListResponse/return');
my $size;

# Reject if it is not a regular file
die "Source-ecaccess-file is not a regular file!\n" if not( @files eq '1' ) or ( $size = $files[0]->{size} ) eq '-1';

# If no target-file is specified then take the source-file name
$targetLocalFile = $files[0]->{name} if not($targetLocalFile);

# Get the file handle
$handle = $controlChannel->getInputFileHandle( $token, $sourceECaccessFile, $opt{offset} )->result;

# Open the target file
open FILE, ">", $targetLocalFile or die "Error creating file: " . $targetLocalFile . "\n";
binmode FILE;

# Open the source file
my $socket = $ecaccess->getFileInputStream($handle);

# Progress bar
my $progressbar;
my $readCount = 0;
my $readTotal = 0;
if ( $opt{progress} && not( $^O =~ /^MSWin/ ) ) {
	eval "use Term::ProgressBar";
	$progressbar = Term::ProgressBar->new( { count => $size, remove => 1 } );
	$progressbar->update(0);
}

# Read the file
while (1) {
	$readCount = $socket->read_entity_body( $data, $opt{bufsize} );
	die "Error downloading file: " . $targetLocalFile . "\n" unless defined $readCount;
	last                                                     unless $readCount;
	$readTotal += $readCount;
	print FILE $data;
	$progressbar->update($readTotal) if ( $opt{progress} && not( $^O =~ /^MSWin/ ) );
}

# Close the file handles
$controlChannel->closeHandle($handle);
close FILE;

# Logout
$ecaccess->releaseToken($token);

__END__

=head1 NAME

ecaccess-file-get - Download an ECaccess File

=head1 SYNOPSIS

B<ecaccess-file-get -version|-help|-manual>

B<ecaccess-file-get [-debug] [-progress] [-offset> I<number>B<] [-bufsize> I<length>B<]> I<source-ecaccess-file> B<[>I<target-local-file>B<]>

=head1 DESCRIPTION

Allow downloading the I<source-ecaccess-file>. If no I<target-local-file> is specified then the
I<source-ecaccess-file> name is used.

The I<source-ecaccess-file> is in the form [domain:][/user-id/]path. Please read the "Shell commands -> File Management"
section of the "ecaccess" guide for more information on the ECaccess File System.

=head1 ARGUMENTS

=over 8

=item I<source-ecaccess-file>

The name of the Source ECaccess File.

=item I<target-local-file> (optional)

The name of the Target Local File.

=back

=head1 OPTIONS

=over 8

=item B<-progress>

Provide a progress meter on the standard terminal, allowing to monitor the file
transmission in real-time. The progress bar is removed from the terminal when
the transmission is done. This option is not supported and ignored on Windows
platforms.

=item B<-offset> I<number>

Every open file has an associated file offset, which determines where the next
read operation will start. This I<number> is set to 0 by default.

=item B<-bufsize> I<length>

Specify the I<length> of the buffer (in bytes) which is used to download the file.
The larger the buffer the smaller the number of http/s requests. By default a
buffer of 1048576 bytes (1MB) is used.

=item B<-version>

Display version number and exits.

=item B<-help>

Print a brief help message and exits.

=item B<-manual>

Prints the manual page and exits.

=item B<-debug>

Display the SOAP messages exchanged.

=back

=head1 EXAMPLES

B<ecaccess-file-get -progress> I<bin/a.out>

Download the I<a.out> File in the $HOME/bin directory of the authenticated user. The Target File Name
is I<a.out>. A progress bar is displayed during the transmission.

=head1 SEE ALSO

B<ecaccess-file-delete>, B<ecaccess-file-chmod>, B<ecaccess-file-mget>, B<ecaccess-file-modtime>, B<ecaccess-file-mput>,
B<ecaccess-file-rmdir>, B<ecaccess-file-copy>, B<ecaccess-file-dir>, B<ecaccess-file-mdelete>, B<ecaccess-file-mkdir>,
B<ecaccess-file-move>, B<ecaccess-file-put>, B<ecaccess-file-size> and B<ecaccess>.

=cut
