#!/usr/bin/perl -w
#
# ecaccess-file-mput: Upload Multiple Local Files on the ECaccess File System at once
#
# Laurent.Gougeon@ecmwf.int - 2010-10-15

use ECMWF::ECaccess;
use Getopt::Long;
use Pod::Usage;
use MIME::Base64;
use Term::Prompt;
use Number::Bytes::Human qw(format_bytes);
use File::Basename;

my %opt = ( progress => 0, force => 0, umask => 640, bufsize => 10485760, version => 0, help => 0, manual => 0, debug => 0 );

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

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

my $targetECaccessDirectory = pop(@ARGV);

@ARGV = map glob, @ARGV if $^O =~ /^MSWin/;

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-local-file(s) specified!\n" ) if not(@ARGV) and not($targetECaccessDirectory);
pod2usage( -noperldoc => 1, -exit => 1, verbose => 0, -msg => "No target-ecaccess-directory specified!\n" ) if not(@ARGV);

# 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();

# Check if the target directory exists and is a directory
pod2usage( -noperldoc => 1, -exit => 1, verbose => 0, -msg => "Target is not a directory!\n" )
  if not( $controlChannel->getFileSize( $token, $targetECaccessDirectory )->result == '-1' );

# If we have a domain with no user specified then include the '.'
$targetECaccessDirectory .= ( $targetECaccessDirectory =~ /\w:$/ ? "." : "" );

# Format the target directory
$targetECaccessDirectory .= ( $targetECaccessDirectory =~ m/\/$/ ? "" : "/" );

# Process all source Files from the command-line
foreach (@ARGV) {

	# Set source and target filenames
	my $source = $_;
	my $target = $targetECaccessDirectory . ( basename($source) );
	my $size;

	# Do we upload this file? (don't process not-plain-files)
	if ( -f $source && ( $opt{force} || &prompt( "y", "Upload " . $source, "y/n", "y" ) ) ) {
		print "Uploading " . $source . " -> " . $target . " (" . ( format_bytes( $size = -s $source ) ) . ") ...\n";

		# 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);
		}

		# Get the file handle
		$handle = $controlChannel->getOutputFileHandle( $token, $target, 0, $opt{umask} )->result;

		# Open the Source File
		open FILE, $source or die "Error opening file: " . $source . "\n";
		binmode FILE;

		# Upload the content
		while ( ( $readCount = read( FILE, $data, $opt{bufsize} ) ) > 0 ) {
			$ecaccess->writeFileOutputStream( $handle, $data );
			$progressbar->update( $readTotal += $readCount ) if ( $opt{progress} && not( $^O =~ /^MSWin/ ) );
		}

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

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

__END__

=head1 NAME

ecaccess-file-mput - Upload Multiple Local Files on the ECaccess File System at once

=head1 SYNOPSIS

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

B<ecaccess-file-mput [-debug] [-progress] [-force] [-umask> I<mode>B<] [-bufsize> I<length>B<]> I<source-local-file> B<[>I<...>B<]> I<target-ecaccess-directory>

=head1 DESCRIPTION

Allow uploading Multiple Local Files on I<target-ecaccess-directory> at once.

The I<target-ecaccess-directory> 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.

Please note this command is not recursive and will only upload plain-files (directories specified as I<source-ecaccess-file>
are ignored).

=head1 ARGUMENTS

=over 8

=item I<source-local-file> B<[>I<...>B<]>

The name(s) of the source File(s).

=item I<target-ecaccess-directory>

The name of the target ECaccess Directory.

=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<-force>

Overrides the interactive mode and upload each file without prompting.

=item B<-umask> I<mode>

The user file-creation I<mode> mask (umask) is used to determine the file permission
for newly created files. The default value is 640.

=item B<-bufsize> I<length>

Specify the I<length> of the buffer (in bytes) which is used to upload the files.
The larger the buffer the smaller the number of http/s requests. By default a
buffer of 10485760 bytes (10MB) 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-mput> I<$HOME/*.txt> I<home:/xyz/>

Upload the local I<$HOME/*.txt> Files in the ECaccess $HOME directory of the user xyz.

=head1 SEE ALSO

B<ecaccess-file-delete>, B<ecaccess-file-get>, B<ecaccess-file-mget>, B<ecaccess-file-modtime>, B<ecaccess-file-chmod>,
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
