package Distribution::TransportAgent;

use strict;

use lib '/app/tools/common/lib';
use Common::Assert;
use Data::Dumper;

# How many retry attempts to make with no progress before failing?
use constant TRANSFER_RETRIES => 3;

# Total number of retries to make, even if there is progress
use constant MAX_RETRIES => 3;

# How long do we wait to attempt a retry?
use constant RETRY_DELAY => 1;

sub new {
    my $class = shift;

    my $self = bless {}, $class;

    return $self->_init(@_);
}

sub _init {
    my $self = shift;
    my %args = @_;

    $self->{_accountName} = $args{account_name} if ( $args{account_name} );
    $self->{_user}        = $args{user}         if ( $args{user} );
    $self->{_passwd}      = $args{passwd}       if ( $args{passwd} );
    $self->{_host}        = $args{host}         if ( $args{host} );
    $self->{_port}        = $args{port}         if ( $args{port} );
    $self->{_authfile}    = $args{authfile}     if ( $args{authfile} );
    $self->{_accountName} = $args{account_name} if ( $args{account_name} );
    $self->{_dontRetry}   = $args{dont_retry}   if ( $args{dont_retry} );
    $self->{_noResume}    = $args{no_resume}    if ( $args{no_resume} );
    $self->{_testing}     = $args{testing}      if ( $args{testing} );

    Common::Log::Debug(" - Setting up Transport Agent ");
    Common::Log::Debug("   + Account Name: $self->{_accountName} ") if ( $self->{_accountName} );
    Common::Log::Debug("   + User: $self->{_user} ")                if ( $self->{_user} );
    Common::Log::Debug("   + Passwd: ******** ")                    if ( $self->{_passwd} );

    #Common::Log::Debug( "   + Passwd: $self->{_passwd} " ) if( $self->{_passwd} );
    Common::Log::Debug("   + Host: $self->{_host} ")         if ( $self->{_host} );
    Common::Log::Debug("   + Authfile: $self->{_authfile} ") if ( $self->{_authfile} );

    $self->testing();

    return $self;
}

sub testing {
    my $self = shift;

    assert( !$self->{_testing}, "Testing option not available for this service" );
}

sub deliver {
    my $self   = shift;
    my $source = shift;
    my $dest   = shift;

    my $retries      = 0;
    my $totalRetries = 0;

    assert( $source, $dest );

    my ( $complete, $transfered );

    do {
        ( $complete, $transfered ) = $self->_transfer( $source, $dest );

        unless ($complete) {

            # Increment retry counter if we have failed
            $retries++ unless ($complete);

            # Increment total retry counter if we have failed
            $totalRetries++ unless ($complete);

            # Reset the return counter if we made any progress
            $retries = 0 if ($transfered);

            Common::Log::Print("Failed attempt #$totalRetries, retries with no progress: $retries");

            # Sleep between retries
            sleep(Distribution::TransportAgent::RETRY_DELAY);
        }

        return $complete if ( $self->{_dontRetry} );

      } while ( !$complete
        && $retries < Distribution::TransportAgent::TRANSFER_RETRIES
        && $totalRetries < Distribution::TransportAgent::MAX_RETRIES );

    return $complete;
}

sub retrieve {
    my $self   = shift;
    my $source = shift;
    my $dest   = shift;

    my $retries      = 0;
    my $totalRetries = 0;

    assert( $source, $dest );

    my ( $complete, $transfered );

    do {
        ( $complete, $transfered ) = $self->_get( $source, $dest );

        unless ($complete) {

            # Increment retry counter if we have failed
            $retries++ unless ($complete);

            # Increment total retry counter if we have failed
            $totalRetries++ unless ($complete);

            # Reset the return counter if we made any progress
            $retries = 0 if ($transfered);

            Common::Log::Print("Failed attempt #$totalRetries, retries with no progress: $retries");

            # Sleep between retries
            sleep(Distribution::TransportAgent::RETRY_DELAY);
        }

      } while ( !$complete
        && $retries < Distribution::TransportAgent::TRANSFER_RETRIES
        && $totalRetries < Distribution::TransportAgent::MAX_RETRIES );

    return $complete;
}

1;
