#!/usr/env perl

use strict;

$|=1;

my $exe = 'pkg-config.exe';
my $version = '1.6.4-2';
my $size = '77123';
my $size_comp = '29461';

my $exegz = $exe . '.gz';

eval { require Prompt::Timeout; };

if ($@) {
  print "\nYou don't have Prompt::Timeout for smooth installation. Using ExtUtils::MakeMaker::prompt() instead\n" .
        "Consider running:\n ppm install Prompt::Timeout\n\n";
  require ExtUtils::MakeMaker;
  ExtUtils::MakeMaker->import();
} else {
  Prompt::Timeout->import();
}

use ExtUtils::Command;
use Config;
use LWP::Simple qw(getstore $ua is_success);
use File::Spec;
use File::Basename;
use IO::Uncompress::Gunzip qw(gunzip $GunzipError) ;

if ($ENV{HTTP_proxy_user} and $ENV{HTTP_proxy_pass} and $ENV{HTTP_proxy} =~ /^http:\/\/([^@]+)$/) {
  my $proxy ="http://$ENV{HTTP_proxy_user}:$ENV{HTTP_proxy_pass}\@" . $1;
  $ua->proxy(['http'], $proxy);
}

my $guess = $Config{'binexp'};

                          
# Search library

if (my $hit = search_for($exe, $guess)) {
  # Check size
  my $size_dll = -s $hit . '/' . $exe;
  if ($size_dll eq $size) {
    print "Using $exe from $hit\n";
    exit;
  }

  print "The executable $exe already exists in $hit, but it has different size.\n" . 
        " Existing: $size_dll bytes\n" .
        " Needed  : $size bytes\n\n" .
        "If it has the same version ($version), it is ok, " .
        "otherwise you may want to download version $version.\n";

  my $proceed = prompt("Fetch $exe? (y/N)", 'Y');
  exit unless $proceed =~ /[Yy]/;

}

print "The executable $exe is needed to complete the installation,\n" .
      "and should be placed in a directory somewhere in your PATH\n" .
      "environment variable. I will fetch and install this for you.\n";
# Fetching 
my $remote = 'http://trouchelle.com/ppm10/scripts/dll/' . $exegz;
print "Fetching $remote ($size_comp bytes) ... ";
while (1) {
  if (is_success(getstore($remote, $exegz))) {
    print " done!\n";
    last;
  } else {
    print ' failed, trying again ... ';
  }
}
# Unpacking
gunzip $exegz => $exe, 'BinModeOut' => 1
  or die "gunzip failed: $GunzipError\nAborting installation\n";
unlink $exegz;

my $base = prompt("Where should $exe be placed?", $guess);

$base =~ s/$exe$//i;
$base =~ s!\\!/!g;
$base =~ s!/$!!;
unless (-d $base) {
  my $ans = prompt("$base does not exist. Create it? (Y/n)", 'Y');
  if ($ans =~ /^[Yy]/) {
    mkdir $base;
  } else {
    exit;
  }
}

if (-f "$base/$exe") {
   my $ans = prompt("$base/$exe exists. Overwrite?", 'Y');
   if ($ans =~ /^[Nn]/) {
     exit;
   }
}

use File::Copy;
move($exe, "$base/$exe");
die ("Moving $exe to $base failed: $!", 'fatal') 
  unless (-f "$base/$exe");
print "$exe has been successfully installed to $base\n";


###

sub search_for {
  my ($exe, $guess) = @_;
  return $guess if (-e File::Spec->catfile($guess, $exe));
  my $hit;
 SEARCH: {
    my $candidate;
    for (File::Spec->path) {
      $candidate = File::Spec->catfile($_, $exe);
      if (-e $candidate) {
        $hit = $candidate;
        last SEARCH;
      }
    }
    my @drives = drives();
    last SEARCH unless (@drives > 0);
    for (@drives) {
      $candidate = File::Spec->catfile($_, $guess, $exe);
      if (-e $candidate) {
        $hit = $candidate;
        last SEARCH;
      }
    }
  }
  return $hit ? dirname($hit) : undef;
}

sub drives {
  my @drives = ();
  eval{require Win32API::File;};
  return map {"$_:\\"} ('C' .. 'Z') if $@;
  my @r = Win32API::File::getLogicalDrives();
  return unless @r > 0;
  foreach (@r) {
    my $t = Win32API::File::GetDriveType($_);
    push @drives, $_ if ($t == 3 or $t == 4);
  }
  return @drives > 0 ? @drives : undef;
}

1;
