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

use strict;
eval{require warnings;1;};

use Logging;
use AgentConfig;
use ArchiveContent::ArchiveContent;

use vars qw|@ISA|;

@ISA = qw|ArchiveContent::ArchiveContent|;

sub new {
  my $self = {};
  bless( $self, shift );
  $self->_init(@_);
  return $self;
}

sub _init {
  my ( $self, $storage, $packer ) = @_;
  $self->{storage} = $storage;
  $self->{packer} = $packer;
  Logging::debug("Windows Archive content transport has been initialized");
}

sub _addTar {
  my $self = shift;
  my $cid_type = shift;
  my $dstFile = shift;
  my %options = @_;
  return undef if $self->_skipContent(%options);
  
  my ( $dir, $file );
  
  if (defined $options{'remoteCommunicationIp'}) {
    
    if( $dstFile =~ m/(.*)\/(.*)/ ){
      $dir = $1;
      $file = $2 . ".zip";
    }
    
    my $archiveResult = $self->_addRemoteTar( $dir, $file, %options);
    return $self->_makeCidNode($dir, $file, $cid_type, $archiveResult, @_);
    
  }
}

sub _addDb {
  my $self = shift;
  my $cid_type = shift;
  my $dstFile = shift;
  my %options = @_;
  return undef if $self->_skipContent(%options);

  my ( $dir, $file );
  
  if( $dstFile =~ m/(.*)\/(.*)/ ){
    $dir = $1;
    $file = $2 . ".zip";
  }
  
  my $archiveResult = $self->_addRemoteDb($dir, $file, %options);
  return $self->_makeCidNode($dir, $file, $cid_type, $archiveResult, @_);
}

sub _addRemoteDb {
  my ( $self, $destDir, $destFile, %options ) = @_;
  
  my $fileName = $self->_prepareDataForRemoteBackupAgent($destDir, $destFile, \%options);
    
  my $response = undef;
    
  $response = $self->_callRemoteDbCommand('backup-db', $fileName);
  
  if ( not defined $response ) {
    return;
  }
  
  $response = $self->_callRemoteDbCommand('get-logs', $fileName);
  
  Logging::debug("Logs from remote node:" . $response);
    
  $response = $self->_callRemoteDbCommand('get-created-content-info', $fileName);
    
  Logging::debug("Logs from remote node:" . $response);

  my $tarResult = $self->_getXmlDataAsPerl($response);
    
  $response = $self->_callRemoteDbCommand('destroy-session', $fileName);
    
  Logging::debug("Logs from remote node:" . $response);
  
  unlink $fileName;
  
  return $tarResult;
}

sub _addRemoteTar {
  my ($self, $destDir, $destFile, %options) = @_;
    
  my $fileName = $self->_prepareDataForRemoteBackupAgent($destDir, $destFile, \%options);
    
  my $response = undef;
    
  $response = $self->_callRemoteCommand('backup-content', $fileName, \%options);
  
  if ( not defined $response ) {
    return;
  }
  
  $response = $self->_callRemoteCommand('get-logs', $fileName, \%options);
  
  Logging::debug("Logs from remote node:" . $response);
    
  $response = $self->_callRemoteCommand('get-created-content-info', $fileName, \%options);
    
  my $tarResult = $self->_getXmlDataAsPerl($response);  
    
  $response = $self->_callRemoteCommand('destroy-session', $fileName, \%options);
    
  Logging::debug("Logs from remote node:" . $response);
  
  unlink $fileName;
    
  return $tarResult;
}

sub _callRemoteDbCommand {
    my ( $self, $command, $fileName ) = @_;
        
    my $remoteExecutorCommand = AgentConfig::getRemoteAgentExecutorCommand();
 
    $remoteExecutorCommand .= " --exec-backup-db ";
    
    $remoteExecutorCommand .= $command;
    
    $remoteExecutorCommand .= " -task-file " . $fileName;
    
    Logging::debug( "Execute backup content on remote host " . $remoteExecutorCommand );
    my $exec = `$remoteExecutorCommand`;
    chomp($exec);
    
    my $retCode = $? >> 8;
    if( $retCode != 0 ){
      Logging::error( "Cannot create content backup on Service Node (ErrorCode: $retCode, STDOUT:$exec) [Error:$!]", 'UtilityError' );
      unlink $fileName;
      return undef;
    }
 
    return $exec;
}

sub _makeCidNode {
  my ($self, $dir, $file, $cid_type, $archiveResult, %options) = @_;
  my $cid = XmlNode->new( 'cid' );
  $cid->setAttribute( 'type', $cid_type );
  $cid->setAttribute( 'unpacksize', '0' );
  $cid->setAttribute( 'path', $dir );
  foreach my $file (@{$archiveResult}) {
    $cid->addChild( XmlNode->new( 'content-file', 'content' => $file->{'filename'}, 'attributes' => {'size' => $file->{'filesize'}}) );
  }

  if (defined($options{'include'})) {
    my @includes = @{$options{'include'}};
    foreach my $inc (@includes) {
      $cid->addChild(XmlNode->new('include-item', 'content' => $inc));
    }
  }

  if (defined($options{'exclude'})) {
    my @excludes = @{$options{'exclude'}};
    foreach my $exc (@excludes) {
      $cid->addChild(XmlNode->new('exclude-item', 'content' => $exc));
    }
  }

  return $cid;
}

sub _prepareDataForRemoteBackupAgent {
    my ($self, $destDir, $destFile, $options) = @_;
    
    # create file with input parameters for $storage->addTar method on remote host
    
    my %perl = {};
    
    foreach my $key (keys %$options) {
      if (ref($options->{$key}) eq 'ARRAY') {
        $perl{$key} = join(",", @{$options->{$key}});
      } else {
        $perl{$key} = $options->{$key};
      }
    }
    
    $perl{'destDir'} = $destDir;
    $perl{'destFile'} = $destFile;
    $perl{'passwd'} = $self->{storage}->{ftpsettings}->{password};
    $perl{'doGzip'} = $self->{storage}->{gzip_bundle};
    $perl{'workDir'} = $self->{storage}->{output_dir};
    $perl{'splitSize'} = $self->{storage}->{split_size};
    $perl{'spaceReserved'} = $self->{storage}->{space_reserved};
    $perl{'sessionId'} = HelpFuncs::mktemp("XXXXXXXX");
    $perl{'passiveMode'} = $self->{storage}->{passive_mode};
    Logging::debug( "sessionId " . $perl{'sessionId'} );
   
    my $xml = $self->_getPerlDataAsXml(\%perl);

    my $fileName = $self->_writeContentToTempFile($xml);
   
    return $fileName;
}

sub _getXmlDataAsPerl {
  my ($self, $xml) = @_;
  
  eval {require XML::Dumper; 1;};
  
  my $dump = new XML::Dumper;
  my $perl = $dump->xml2pl($xml);
  return $perl;
}

sub _getPerlDataAsXml {
  my ($self, $perl) = @_;
  
  eval {require XML::Dumper; 1;};
  
  my $dump = new XML::Dumper;
  my $xml = $dump->pl2xml($perl);
  return $xml;
}

1;