#!/usr/bin/perl -w

use strict;

use lib '/app/tools/common/lib';
use Common::RSDB;

use Getopt::Std;
use File::Basename;
use Term::ProgressBar;
use Data::Dumper;

use constant SSH       => '/usr/bin/ssh';
use constant WC        => '/usr/bin/wc';
use constant MYSQL     => '/usr/bin/mysql';
use constant MYSQLDUMP => '/usr/bin/mysqldump';

my %opt;
usage() unless getopts( 'bu:p:h:c:s:i:ld', \%opt );

my $id = $opt{c};

if ( $opt{l} ) {
    list_clients( $ARGV[0] );
    exit 1;
}

my $debug = 1 if ( $opt{d} );

unless ( defined($id) ) {
    print STDERR "ERROR: CLIENTID required.  Use rsdb to find one\n";
    usage();
}

my $client_hashref = $Common::RSDB::CLIENT_DB{$id};
my $host = $opt{h} ? $opt{h} : $client_hashref->{host_id};

my $infile = $opt{i};
my $outfile = $opt{s} || '/dev/null';

my $mysqldump_opts = "--add-drop-database";

die "Unknown client id: $id" unless $client_hashref;

#if( ! $host ) {
#    print STDERR "ERROR: -h option required for RSCOMMON (client 0)\n";
#    usage();
#}

if ( $opt{b} ) {
    restore_from_production($id);
    exit 1;
}

if ( defined( $opt{p} ) ) {
    $client_hashref->{password} = $opt{p};
}

if ( $opt{u} ) {
    $client_hashref->{username} = $opt{u};
}

if ( $outfile && -e $outfile && !-w $outfile ) {
    die "Can not write to output file: $outfile";
}

if ( $infile && !-r $infile ) {
    die "Can not read from input file: $infile";
}

my $cmd = sprintf(
    "%s %s '%s -u%s %s -h%s -B %s %s | %s -l'",
    SSH, $host, MYSQLDUMP,
    $client_hashref->{username},
    $client_hashref->{password} ? "-p$client_hashref->{password}" : "",
    $client_hashref->{server},
    $client_hashref->{db_name},
    $mysqldump_opts, WC
);
if ($infile) {
    $cmd = sprintf( "%s -l %s | awk '{print \$1}'", WC, $infile );
}

print STDERR "Running: $cmd\n" if ($debug);

open( INFILE, "$cmd |" ) || die "Failed to run command: $cmd";

my $count = <INFILE>;
chomp($count);
close(INFILE);

die "No lines read for import" unless ($count);

$cmd = sprintf(
    "%s %s %s -u%s %s -h%s -B %s %s",
    SSH, $host, MYSQLDUMP,
    $client_hashref->{username},
    $client_hashref->{password} ? "-p$client_hashref->{password}" : "",
    $client_hashref->{server},
    $client_hashref->{db_name},
    $mysqldump_opts
);

print STDERR "Running: $cmd\n" if ( $debug && !$infile );

open( DUMPOUT, ">$outfile" ) || die "Failed to open output file";

if ($infile) {
    open( INFILE, "$infile" ) || die "Failed to open input file: $infile";
} else {
    open( INFILE, "$cmd |" ) || die "Failed to run command: $cmd";
}

my @mysqldump;
my $read_progress = Term::ProgressBar->new( { count => $count, name => "reading" } );
while (<INFILE>) {
    $read_progress->update();
    push( @mysqldump, $_ );
    print DUMPOUT $_;
}
close(INFILE);
close(DUMPOUT);
print "\n";

$cmd = MYSQL . " -uroot";
print STDERR "Running: $cmd\n" if ($debug);

open( OUTFILE, "| $cmd" ) || die "Failed to run command: $cmd";

print STDERR "importing " . @mysqldump . " lines\n" if ($debug);
print STDERR "Running: $cmd\n" if ($debug);

my $write_progress = Term::ProgressBar->new( { count => $count - 1, name => "writing" } );

foreach (@mysqldump) {
    $write_progress->update();
    print OUTFILE "$_\n";

    #print STDERR "$_\n" if( $debug );
}

close(OUTFILE);

sub usage {
    my $prog = basename $0;

    print <<EofUSAGE;

usage: $prog [-h host][-s dumpfile][-i dump_input][-c id][-u user][-p passwd][-d][-l hostpatern]
            -b - Restore from production snapshot
            -h - Override the host to pull data from
            -c - Client ID for the data
            -l - List client ids (host pattern is optional)
            -i - Read from dump file
            -s - Save dump file
            -u - override mysql username
            -p - override mysql password
            -d - display debug information
EofUSAGE

    exit 1;
}

sub list_clients {
    my $host = shift;
    my $key;
    foreach $key ( sort { $a <=> $b } keys(%Common::RSDB::CLIENT_DB) ) {
        printf( "%-20s %-10s ID: %s\n", $Common::RSDB::CLIENT_DB{$key}->{db_name}, "($Common::RSDB::CLIENT_DB{$key}->{host_id})", $key )
          if ( !defined($host) || $Common::RSDB::CLIENT_DB{$key}->{db_name} =~ /$host/i );
    }
}

# This will only work if you have SSH keys setup to the production web and DB servers.
sub restore_from_production {
    my $clientID = shift;
    my $destdir  = '/space/mysql/current';
    my $client   = $Common::RSDB::CLIENT_DB{$clientID};
    my $webhost  = $client->{host_id};
    my $dbhost   = $client->{server};
    my $dbname   = $client->{db_name};

    # set a sudo password token so the next commond can be passwordless.
    system("sudo ls >/dev/null");

    # Build the command to download and restore the snapshot
    my $cmd =
      "cd $destdir; ssh $webhost ssh $dbhost cat `ssh $webhost ssh $dbhost ls /app/backup/snapshots/$dbname* | tail -1` | sudo tar xvfz -";

    # Now run the command;
    system($cmd );

    print "Restarting Mysql\n";
    system("sudo /etc/init.d/mysql restart");

    return 1;
}
