#!/usr/bin/perl 

use strict;
use Term::ANSIColor;

# install the latest perl via perlbrew

# args for perl build
my $build_args="-Dusethreads -Duselargefiles -Dcccdlflags=-fPIC -Dpager=/usr/bin/sensible-pager -Doptimize='-O3 -march=native -mtune=native'";

my $args = "@ARGV"; # cmd line args

# get number of cpus
my $ncpus=`cat /proc/cpuinfo |grep processor | wc -l`;
chomp $ncpus;
$ncpus = $ncpus<1 ? 1 : $ncpus;

# 0 get latest perlbrew, check cpanm is installed
print "Installing latest perlbrew...\n";
runcmd("curl -skL http://install.perlbrew.pl | bash");
print "Version ",(`perlbrew version`=~/App\:\:perlbrew\/(\S+)/)[0]," installed\n";
print "Installing patchperl...\n";
runcmd("perlbrew -v -f install-patchperl");
print "Installing cpanm...\n";
runcmd("perlbrew -v -f install-cpanm");

# 1 get latest perl number

my $latest_version=
    (sort versioncmp grep {/perl-(\d+\.\d+\.\d+)/ && s/^\s*// && s/\s*$//} `perlbrew available --all`)[-1];

print "Latest perl is $latest_version\n";

# 2 get currently installed perl
my $current_version = (`perlbrew use`=~/Currently using (\S+)/)[0];

print "Currently using $current_version\n";

my $vcmp = versioncmp($current_version,$latest_version);

if($vcmp==-1 || $args=~/force/i)
{
    print "A newer version of perl ($latest_version) is available\n";

    # 3 get currently installed module list, save it
    my @current_modules = `perlbrew list-modules`;
    print "Currently there are ",$#current_modules+1," installed\n";
    my $f="$ENV{HOME}/.perlbrew/$current_version.modules";
    {
	`mkdir -p $ENV{HOME}/.perlbrew`;
	open(my $fp,">$f")||die("cannot save module list in $f");
	map{print {$fp} $_,"\n"}@current_modules;
	close $fp;
    }

    # 4 install new perl 
    if($vcmp==-1)
    {
	print "Installing new perl $latest_version on $ncpus CPUs\n";
	runcmd("perlbrew -v install $latest_version $build_args -j $ncpus");
    }

    # 5 install cpanm with new perl
    runcmd("perlbrew switch $latest_version ; perlbrew --force install-cpanm");

    # 6 install modules (with notest and reinstall)
    print "Re-install modules for $latest_version\n";
    runcmd("perlbrew -v list-modules |grep -v ^Perl\$ | perlbrew exec --with $latest_version cpanm --reinstall --notest ");

    # 6b modules which are always ignored (no idea why)
    #    but can be installed now
    runcmd("perlbrew switch $latest_version ; cpanm Gtk2::Ex::NoShrink");

    # 7 install rob's modules
    print "Installing Rob's modules";
    runcmd("perlbrew switch $latest_version ; cd $ENV{HOME}/progs/perl/modules; ./install_perl_mods.pl");
}
else
{
    print "No update is available\n";
}

exit;


sub versioncmp( $$ ) {

    # from Versions.pm

    my @A = ($_[0] =~ /([-.]|\d+|[^-.\d]+)/g);
    my @B = ($_[1] =~ /([-.]|\d+|[^-.\d]+)/g);

    my ($A, $B);
    while (@A and @B) {
	$A = shift @A;
	$B = shift @B;
	if ($A eq '-' and $B eq '-') {
	    next;
	} elsif ( $A eq '-' ) {
	    return -1;
	} elsif ( $B eq '-') {
	    return 1;
	} elsif ($A eq '.' and $B eq '.') {
	    next;
	} elsif ( $A eq '.' ) {
	    return -1;
	} elsif ( $B eq '.' ) {
	    return 1;
	} elsif ($A =~ /^\d+$/ and $B =~ /^\d+$/) {
	    if ($A =~ /^0/ || $B =~ /^0/) {
		return $A cmp $B if $A cmp $B;
	    } else {
		return $A <=> $B if $A <=> $B;
	    }
	} else {
	    $A = uc $A;
	    $B = uc $B;
	    return $A cmp $B if $A cmp $B;
	}	
    }
    @A <=> @B;
}


sub runcmd
{
    my $cmd=join(' ',@_);

    print "Execute : ",color('red'),$cmd,color('reset'),"\n\n";
    open(my $fp,$cmd.'|')||die("cannot open $cmd for reading");
    while(my $l=<$fp>)
    {
	print color('yellow'),$l,color('reset');
    }
    close $fp;
    my $ret = $?;
    print "Command returned $ret\n";
    if($ret != 0)
    {
	print "Command \"$cmd\" returned error (status $ret) : attempting to continue\n";
    }
}
