# Copyright 1999-2016. Parallels IP Holdings GmbH. All Rights Reserved.
package Storage::ArchiveStorage;

use strict;
use warnings;

use File::Basename qw(basename);
use IPC::Run;
use HelpFuncs;
use Logging;
use Storage::Storage;

use vars qw|@ISA|;
@ISA = qw|Storage::Storage|;

sub _init {
  my ($self, %options) = @_;

  $self->SUPER::_init(%options);
  $self->{exportDir} = $options{'export-dir'};
  $self->{ftp} = $options{'ftp'};
  $self->{sessionPath} = $options{'session-path'};
  $self->{verbose} = $options{'verbose'};
  $self->{cmd} = undef;
  $self->{cmdInput} = '';
  if ($self->{sessionPath}) {
    $self->{cmdOutputPath} = $self->{sessionPath} . '/export-dump-result';
  } else {
    $self->{cmdOutputPath} = HelpFuncs::mktemp(AgentConfig::getBackupTmpDir() . '/export-dump-result-XXXXXXXX');
  }
  $self->{keepLocalBackup} = $options{'keep-local-backup'};

  Logging::debug("-" x 60);
  Logging::debug("ARCHIVE storage initialized.");
  Logging::debug("Base directory: $self->{output_dir}");
  Logging::debug("Space reserved: $self->{space_reserved}");
  Logging::debug("Gzip bundles: " . ($self->{gzip_bundle} ? "yes" : "no"));
  Logging::debug("Bundle split size: " . ($self->{split_size} || "do not split"));
  Logging::debug("-" x 60);
  $self->reserveSpace();
}

sub DESTROY {
  my $self = shift;
  unlink($self->{cmdOutputPath});
  $self->SUPER::DESTROY();
}

sub finishExport {
  my $self = shift;

  my $mainDumpFile = $self->getMainDumpXmlRelativePath();
  if ($mainDumpFile) {
    my $mainDumpFileName = basename($mainDumpFile);
    Logging::debug("Add file $mainDumpFileName to archive");
    $self->{cmdInput} .= "$mainDumpFileName\n";
    eval {
      IPC::Run::pump($self->_getCmd());
    };
    if ($@) {
      Logging::debug($@);
    }
  }
  eval {
    $self->_finishCmd();
  };
  if ($@) {
    if ($self->{keepLocalBackup}) {
      Logging::warning($@);
    } else {
      die($@);
    }
  }
}

sub createRepositoryIndex{
  my ($self, $index) = @_;
}

sub writeDiscovered{
  my $self = shift;

  $self->_writeDiscovered(@_);
}

sub moveFileToDiscovered {
  my $self = shift;

  $self->_moveFileToDiscovered(@_);
}

sub addTar {
  my $self = shift;

  my ($ret, $destDir, $files) = @{$self->_addTar(@_)};
  return $ret unless $ret;

  my $file;
  eval {
    my $dumpStorage = $self->{mainDumpRootPath} ? sprintf('%s/%s', $self->{output_dir}, $self->{mainDumpRootPath}) : $self->{output_dir};
    my $destDirRelativePath = substr($destDir, length($dumpStorage));
    $destDirRelativePath =~ s/^\/+//;
    foreach my $fileInfo (@{$files}) {
      my ($fileName) = @{$fileInfo};
      $file = $destDirRelativePath ? sprintf('%s/%s', $destDirRelativePath, $fileName) : $fileName;
      Logging::debug("Add file $file to archive");
      $self->{cmdInput} .= "$file\n";
      IPC::Run::pump($self->_getCmd());
    }
  };
  if ($@) {
    Logging::debug($@);
    if (!$self->{keepLocalBackup}) {
      Logging::error(sprintf('Unable to upload the archive %s to the FTP storage: %s', $file, $self->_getCmdOutput()));
      if ($self->{sessionPath}) {
        Logging::serializeXmlLog("$self->{sessionPath}/migration.result");
      }
      exit(0);
    }
  }
  return $ret;
}

sub _getCmd {
  my $self = shift;

  if (!$self->{cmd}) {
    my $command = [AgentConfig::pmmRasBin(), '--export-dump-as-file'];
    if ($self->{ftp}) {
      $ENV{'DUMP_STORAGE_PASSWD'} = $self->{ftp}->{password};
      push(@{$command}, '--dump-file-specification', sprintf('%s/%s', HelpFuncs::getStorageUrlFromFtpSettings($self->{ftp}), $self->{exportFileName}));
      push(@{$command}, '--use-ftp-passive-mode') if exists($self->{ftp}->{'passive'});
    } else {
      push(@{$command}, '--dump-file-specification', sprintf('%s/%s', $self->{exportDir}, $self->{exportFileName}));
    }
    push(@{$command}, '--dump-storage', sprintf('%s/%s', $self->{output_dir}, $self->{mainDumpRootPath}));
    push(@{$command}, '--split-size', $self->{split_size}) if $self->{split_size};
    push(@{$command}, '--session-path', $self->{sessionPath}) if $self->{sessionPath};
    push(@{$command}, '--debug', '--verbose') if $self->{verbose};
    Logging::debug('Start: ' . join(' ', @{$command}));
    $self->{cmd} = IPC::Run::start($command, \$self->{cmdInput}, "1>$self->{cmdOutputPath}", '2>/dev/null');
  }
  return $self->{cmd};
}

sub _finishCmd {
  my $self = shift;

  if ($self->{cmd}) {
    my @createdVolumes = ();
    eval {
      $self->{cmd}->finish();
    };
    if ($@) {
      Logging::debug($@);
    }
    if ($@ || $self->{cmd}->result()) {
      die(sprintf('Unable to upload the backup to the FTP storage: %s', $self->_getCmdOutput()));
    }
    my $cmdOutput = $self->_getCmdOutput();
    @createdVolumes = split("\n", $cmdOutput) if $cmdOutput;
    $self->{cmd} = undef;
    $self->{cmdInput} = '';
    unlink($self->{cmdOutputPath});
    $self->{createdVolumes} = \@createdVolumes;
  }
}

sub _getCmdOutput {
  my $self = shift;
  my $cmdOutput = '';
  if (open(RESULT, $self->{cmdOutputPath})) {
    while (<RESULT>) {
      $cmdOutput .=  $_;
    }
    close RESULT;
  }
  return $cmdOutput;
}

1;
