#!/usr/bin/perl
use strict;
use warnings;
use PAR::Dist;
use Getopt::Long;
use File::Spec;
use Data::Dumper;
use PAR::Dist::FromCPAN;
use File::Copy qw/move/;
use Cwd qw/cwd/;

my $verbose;
sub _diag ($) {
  print @_, "\n" if $verbose;
}

my $usage = <<HERE;
Usage: $0 -d BZDIR -o OUTDIR [-v] [--optional]
HERE

my $bzdir;
my $odir;
my $optional_pars = 0;

GetOptions(
  'd|bugzilla-directory=s' => \$bzdir,
  'o|output-directory=s' => \$odir,
  'v|verbose' => \$verbose,
  'optional' => \$optional_pars,
);

die $usage
  if not defined $bzdir
  or not -d $bzdir
  or not defined $odir;

if (-d $odir) {
  die "Output directory '$odir' exists. Please remove it.\n";
}

mkdir($odir) or die $!;

$bzdir = File::Spec->rel2abs($bzdir);
$odir = File::Spec->rel2abs($odir);

_diag "Changing to output dir $odir...";
chdir($odir);

# load Bugzilla module path
require lib;
lib->import($bzdir);

# fetch required and optional modules from bugzilla itself
my %envcopy = %ENV;
require Bugzilla;
require Bugzilla::Install::Requirements;
my $required = &Bugzilla::Install::Requirements::REQUIRED_MODULES;
my $optional = &Bugzilla::Install::Requirements::OPTIONAL_MODULES;
%ENV = %envcopy;

_diag "Creating .par files for the required modules...";
mkdir('required');
mkdir('required_binary');
create_pars($required, 'required', 'required_binary');

if ($optional_pars) {
  _diag "Creating .par files for the optional modules...";
  mkdir('optional');
  mkdir('optional_binary');
  create_pars($optional, 'optional', 'optional_binary');
}

sub create_pars {
  my $mods = shift;
  my $portable_dir = shift;
  my $binary_dir = shift;
  my $workdir = cwd();
  foreach my $mod (@$mods) {
    _diag "Creating .par file for module '$mod->{module}' in package '$mod->{package}'...";
    cpan_to_par(
      out => '.',
      pattern => $mod->{module},
      follow => 1,
      strip_docs => 1,
    );

    # move the resulting files to the portable/binary directories
    chdir($workdir);
    opendir my $dh, '.' or die $!;
    my @files = grep { /\.par$/ } readdir($dh);
    close $dh;
    foreach my $file (@files) {
      _diag "Trying to determine whether $file contains binary code...";
      my $isbinary = PAR::Dist::contains_binaries($file);
      if ($isbinary) {
        _diag "Determined that $file contains binaries...";
        move($file, $binary_dir) or die $!;
      }
      else {
        _diag "Determined that $file should be portable...";
        move($file, $portable_dir) or die $!;
      }
    }
  }
}

