#!/usr/bin/perl
# Copyright 1999-2014. Parallels IP Holdings GmbH. All Rights Reserved.

use strict;

# Prefer internal modules over external
use lib '.';

use Agent;
use AgentConfig;
use CompatArgParse;
use DumpStatus;
use Logging;
use XmlNode;
use DumpComposer;

use sigtrap qw(die normal-signals);
use POSIX qw(:signal_h);
use Carp qw( confess );

sub printHelp {
  print <<'HELP';

Usage:
  $0 <command> [<options>]

Commands:
  -s |--get-status           get status of the host: is this agent applicable
  -dr|--dump-resellers=<list> comma-separated list of clients to dump
  -dc|--dump-clients=<list>  comma-separated list of clients to dump
  -dd|--dump-domains=<list>  comma-separated list of domains to dump
  -da|--dump-all             dump all objects on hosts
  -lc|--get-content-list     get list of content files
  -h |--help                 this help

Options:
      --server               dump server settings (may be used as independent command)
  -nc|--no-content           make a shallow structure dump
  -co|--configuration-only   dump only configuration
  -om|--only-mail            dump only mail content
  -oh|--only-hosting         dump only hosting
  -nz|--no-compress          do not compress content files
  -dt|--dump-child           dump child`s objects
      --content-transport    type of transport used for content ("archive"|"rsync"). Default is "archive"

  -ss|--split-size=<size>    Split the dump to the parts of <size>.
                             Additional parts have .001, .002... suffixes.
                             Dump is not split if such option is not given.

  -d |--description=<text>   Add description to the dump

  -v |--verbosity=<1-5>      Verbosity level. Default 5

HELP
}

sub main {
  my $sigset = POSIX::SigSet->new;
  sigprocmask( SIG_SETMASK, $sigset );

  $SIG{__DIE__} =  \&confess;

  my %arg_opts = (
    '--help|-h'                => '',
    '--get-status|-s'          => '',
    '--dump-resellers|-dr'     => 's',
    '--dump-clients|-dc'       => 's',
    '--dump-domains|-dd'       => 's',
    '--dump-all|-da'           => '',
    '--dump-child|-dt'         => '',
    '--get-content-list|-lc'   => '',
    '--no-content|-nc'         => '',
    '--only-mail|-om'          => '',
    '--only-hosting|-oh'       => '',
    '--no-compress|-nz'        => '',
    '--configuration-only|-co' => '',
    '--server'                 => '',
    '--content-transport'      => '',
    '--output|-o'              => 's',
    '--split-size|-ss'         => 's',
    '--description|-d'         => 's',
    '--verbosity|-v'           => 's'
  );

  my $args = CompatArgParse::parse( \@ARGV, \%arg_opts );
  # reduce verbosity level for get-content-list output
  Logging::setVerbosity( 2 );

  if ( exists $args->{'get-content-list'} ) {
    open(CONTENT_FILE, "<", AgentConfig::cwd()."/content-list.xml") || die "Couldn't get content list: $!\n";
    undef $/;
    my $content = <CONTENT_FILE>;
    print $content;
    return 0;
  }

  if ( exists $args->{'help'} ) {
    printHelp();
    return 0;
  }

  # set up default verbosity
  Logging::setVerbosity( 3 );
  if ( exists $args->{'verbosity'} ) {
    Logging::setVerbosity( $args->{'verbosity'} );
  }

  if ( exists $args->{'get-status'} ) {
    my $statusNode = Agent::getAgentStatus();
    $statusNode->serialize( \*STDOUT );
    return 0;
  }

  my $do_gzip = exists $args->{'no-compress'} ? undef : 1;

  Logging::setXmlLogging();

  if ( ( exists $args->{'content-transport'} ) && ( $args->{'content-transport'} eq 'rsync' ) ) {
    my $transport_host = <STDIN>;
    chomp $transport_host;
    my $transport_login = <STDIN>;
    chomp $transport_login;
    my $transport_passwd = <STDIN>;
    chomp $transport_passwd;
    my $transport_port = <STDIN>;
    chomp $transport_port;
    my %transportOpt;
    $transportOpt{'host'} = $transport_host;
    $transportOpt{'login'} = $transport_login;
    $transportOpt{'passwd'} = $transport_passwd;
    $transportOpt{'port'} = $transport_port if $transport_port;
    Agent::setContentTransport('rsync', \%transportOpt);
  }
  
  my ($storage, $status, $no_content, $only_mail, $only_hosting);

  if ( exists $args->{'no-content'} ) {
    # should be passed to Composer
    $no_content = 1;
  }

  if ( exists $args->{'configuration-only'} ) {
    # should be passed to Composer
    $no_content = 1;
  }

  die "Cannot use 'only-mail' and 'only-hosting' at one time. Use only one of them."
    if exists $args->{'only-mail'} and exists $args->{'only-hosting'};

  if ( exists $args->{'only-mail'} ) {
    # should be passed to Composer
    $only_mail = 1;
  }

  if ( exists $args->{'only-hosting'} ) {
    # should be passed to Composer
    $only_hosting = 1;
  }

  if ( exists $args->{'description'} ) {
    # seems like useless for migration
  }

  my (@domains, @clients, @resellers);

  if ( exists $args->{'dump-all'} ) {
    Logging::debug("Selected all objects");
  }
  else{
      my $dumpchild = 0;
      $dumpchild = 1 if exists $args->{'dump-child'};
      if ( exists $args->{'dump-domains'} ) {
        my $value = $args->{'dump-domains'};
        if ( $value eq "-" ) {
          $value = <STDIN>;
          chomp $value;
        }
        @domains = split( /\s*,\s*/, $value );
        Logging::debug( "Selected domains: " . join( ", ", @domains ) );
      }
      elsif( not $dumpchild ){
        my @empty;
#       $agent->excludeDomains(@empty);
      }

      if ( exists $args->{'dump-clients'} ) {
        die ("Command 'dump-clients' does not supported");
#        my $value = $args->{'dump-clients'};
#        if ( $value eq "-" ) {
#          $value = <STDIN>;
#          chomp $value;
#        }
#        @clients = split( /\s*,\s*/, $value );
#        Logging::debug( "Selected clients: " . join( ", ", @clients ) );
#        $agent->selectClients(@clients);
      }
      elsif( not $dumpchild ){
        my @empty;
#       $agent->excludeClients(@empty);
      }

      if ( exists $args->{'dump-resellers'} ) {
        die ("Command 'dump-resellers' does not supported");
#        my $value = $args->{'dump-resellers'};
#        if ( $value eq "-" ) {
#          $value = <STDIN>;
#          chomp $value;
#        }
#        @resellers = split( /\s*,\s*/, $value );
#        Logging::debug( "Selected resellers: " . join( ", ", @resellers ) );
#        $agent->selectResellers(@resellers);
      }
      elsif( not $dumpchild ){
        my @empty;
#       $agent->excludeResellers(@empty);
      }
  }

  if ( exists $args->{'server'} ) {
    Logging::warning("Command 'server' does not supported in current version. Server wide settings will be skipped");
  }

  unless (   exists $args->{'dump-all'} 
          || exists $args->{'dump-resellers'}
          || exists $args->{'dump-clients'}
          || exists $args->{'dump-domains'} ) {
    printHelp();
    return 0;
  }

  my $dumpNode;
  if (exists $args->{'dump-all'} && exists $args->{'no-content'}) {
    $dumpNode = DumpComposer::makeShallowDump(AgentConfig::cwd());
  }else {
    $dumpNode = DumpComposer::makeDump(AgentConfig::cwd(), 
               scalar (@resellers) > 0 ? \@resellers : undef, 
               scalar (@clients) > 0 ? \@clients : undef, 
               scalar (@domains) > 0 ? \@domains : undef, 
               $no_content, $only_mail, $only_hosting, $do_gzip);
  }

  if ( ref($dumpNode) =~ /XmlNode/ ) {
    Logging::debug("Migration dump is successfully saved.");
  }
  else {
    Logging::error("Migration dump is not saved.");
  }

  return 0;
}

sub writeMigrationResult{
  my $sessionPath = AgentConfig::cwd();
  Logging::serializeXmlLog("$sessionPath/migration.result");
  return;
}

my $exitcode = main();
writeMigrationResult();
exit( $exitcode );

