#!/usr/bin/env perl

=head1 LICENSE

Copyright (c) 2007-2011 Illumina, Inc.

This software is covered by the "Illumina Genome Analyzer Software 
License Agreement" and the "Illumina Source Code License Agreement", 
and certain third party copyright/licenses, and any user of this 
source file is bound by the terms therein (see accompanying files
Illumina_Genome_Analyzer_Software_License_Agreement.pdf and
Illumina_Source_Code_License_Agreement.pdf and third party 
copyright/license notices).

This file is part of the Consensus Assessment of Sequence And VAriation
(CASAVA) software package.

=head1 NAME

configureAlignment.pl - Create and initialize the Alignment folder.

=head1 SYNOPSIS

configureAlignment.pl [config.txt|-] [options]

Options:

=over 4

=item B<--help> brief help message

Z<>

=item B<--man> full documentation

Z<>

=item B<--make>

Create and initialize the analysis folder. If --make is not set, only the
configuration validation is performed. 

=item B<--EXPT_DIR=<path>> full path to the experiment directory

Z<>

=item B<--OUT_DIR=<path>> full path to the output directory

Z<>

=item B<Running the small test data set included with CASAVA>

 @CASAVA_FULL_BINDIR@/configureAlignment.pl \
 --make \
 --OUT_DIR ./Aligned \
 --EXPT_DIR @CASAVA_FULL_DATADIR@/examples/Validation/Default/Unaligned \
 @CASAVA_FULL_DATADIR@/examples/Validation/Default/Aligned/ValidationConfig.txt

 make -C Aligned  # use make -j <parallel jobs> to speedup the conversion

=back

=head1 DESCRIPTION

This script is a complete rewrite of the GERALD.pl originally 
implemented for the Pipeline.

Parse the program options:
 - command line options
 - options from the config.txt

Generate the config.xml file (validate against the official DTD)

Generate the makefile (new generation of Makefile light)

run self_test

report completion

=head1 DIAGNOSTICS

=head2 Exit status

=over 4

=item B<0:> successful completion

=item B<1:> abnormal completion

=item B<2:> fatal error

Z<>

=item B<Errors:> All error messages are prefixed with "ERROR: ".

Z<>

=item B<Warnings:> All warning messages generated by CASAVA are prefixed with "WARNING: ".

Z<>

=back

=head1 BUGS AND LIMITATIONS

There are no known bugs in this module.

All documented features are fully implemented.

Please report problems to Illumina Technical Support (support@illumina.com)

Patches are welcome.

=head1 AUTHOR

Anthony J. Cox

Come Raczy

=cut

use lib '@CASAVA_FULL_PERL_LIBDIR@'; # substituted by CMake during install

use warnings "all";
use strict;

# parse thecommand line arguments
use Getopt::Long;
use Pod::Usage;

use Casava::Common::Log qw(initLog logInfo errorExit);
use Casava::Alignment;
use Casava::Alignment::Config;

$ENV{PATH} = $1 if $ENV{PATH}=~/^(.*)$/;

initLog( undef, 3, 0, 1, 1);

sub _generateGeraldFolderName
{
    my ($exptdir) = @_;

    my $outputDir;
    my ($vol, $dirs, $lastDir) = File::Spec->splitpath($exptdir);
    my @directories = File::Spec->splitdir($dirs);
    pop @directories if !$directories[-1];
    if ('Unaligned' eq $lastDir && scalar(@directories))
    {
        $outputDir = File::Spec->catdir($vol, @directories, 'Aligned');
        logInfo "--OUT_DIR is unspecified. Will configure the conversion in $outputDir\n"
    }
    else
    {
        errorExit "ERROR: --OUT_DIR is unspecified and impossible to guess\n"
    }
    return $outputDir;
}


my $COMMAND_LINE = join(" ", $0, @ARGV);

# load the default configuration parameters before parsing the command line
my $config = Casava::Alignment::Config->new;
my $CASAVA_DATADIR = '@CASAVA_FULL_DATADIR@'; # substituted during the install
my $geraldXmlFile = File::Spec->catfile($CASAVA_DATADIR, 'GERALD.xml');
open my $geraldXmlHandle, "<", $geraldXmlFile or errorExit("Failed to open $geraldXmlFile: $!");
$config->loadDefaults($geraldXmlHandle);
my %geraldVariables = $config->getDefaultVariables;

#print STDERR Dumper::Dumper(%geraldVariables);

my $man = 0;
my $help = 0;
my $make = 0;
my $sampleSheetFile;
my $skipVariableMetadata = 0;

my %programOptions = (
                      make => \$make,
                      'sample-sheet' => \$sampleSheetFile,
                      'skip-variable-metadata' => \$skipVariableMetadata,
                      help => \$help,
                      man => \$man,
                     );

GetOptions(\%programOptions,
           'make', 'help|?', 'man', 'skip-variable-metadata!', map("$_=s", keys %geraldVariables)) or pod2usage(2);

pod2usage(1) if $help;
pod2usage(-exitstatus => 0, -verbose => 2,  -input => $1) if ($man and $0 =~ /(.*)/);
pod2usage("$0: No configuration file given.\n")  if (1 > @ARGV);
pod2usage("$0: Too many configuration files.\n")  if (1 < @ARGV);

my $configTxt = $ARGV[0];

# remove the options that shouldn't go into the configuration file
delete @programOptions{qw(make help man sample-sheet skip-variable-metadata)};

# update the configuration with the values from the given configuration file
$config->readTxt($configTxt, 'check');

# update the configuration with the values given on the command line
foreach my $name (keys %programOptions)
{
    $config->setDefaultVariable($name, $programOptions{$name}, 'check');
}

# Provide a default OUT_DIR if needed
$config->setDefaultVariable('EXPT_DIR', File::Spec->rel2abs($config->getVariable(name => 'EXPT_DIR')));
my $exptDir = $config->getVariable(name => 'EXPT_DIR');
my $outDir = $config->getVariable(name => 'OUT_DIR');
$config->setDefaultVariable('OUT_DIR', _generateGeraldFolderName($exptDir)) unless defined $outDir and 0 < length($outDir);
# Make OUT_DIR absolute if needed
$config->setDefaultVariable('OUT_DIR', File::Spec->rel2abs($config->getVariable(name => 'OUT_DIR')));


# load the run parameters from the EXPT_DIR config.xml
$config->getRunParameters;

# validate the given configuration
$config->validate;

# always print the configuration
print $config->toXml;

# initialize the analysis folder if required
if ($make)
{
    Casava::Alignment::initialize($config, $sampleSheetFile, $configTxt, $COMMAND_LINE, $skipVariableMetadata);
    my $outputDirectory = $config->getVariable(name => 'OUT_DIR');
    Casava::Alignment::selfTest($outputDirectory, $sampleSheetFile);
}

__END__
