#!/usr/bin/env perl
# PROJECT: CASAVA
# MODULE:  $RCSfile: sortExport.pl,v $
# AUTHOR:  Richard Carter
#
# Copyright (c) 2008 Illumina
# 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).

use warnings FATAL => 'all';
use strict;
use POSIX qw(strftime);

use File::Spec;
use IO::File;
use Sys::Hostname;
use Getopt::Long;
use File::Copy qw(move);
use File::Temp;

use lib '/home/psgendb/local/pkg/CASAVA_v1.8.2-build/lib/CASAVA-1.8.2/perl';
use Casava::Common::Log;
use Casava::Common::IOLib qw(executeCmd genId createDirs);

use Casava::PostAlignment::Sequencing::Config qw(loadConfiguration updateProjectConfValue
  %CONF_APP %CONF_PROJ %CONF_RUN %runsConfig readProjectParameters);
use Casava::PostAlignment::Sequencing::GenomicIOLib qw(configureReadStorage rewindTo
  getNextRead writeRead %exportFields %doubleExportFields @nmnmTags);
use Casava::PostAlignment::Sequencing::Target
  qw(checkTarget splitPEexport splitSEexport commitExportSplit);
# use Casava::PostAlignment::Sequencing::SortLib qw(sortFileList);

#$| = 1;
my $usage = "sortExport.pl <project directory>\n";

my $projectDir          = "";
my $help                = 0;
my $binId               = 0;
my $chrom               = "";
my $target              = "";
my $buildFilePath       = '';
my $read1ExportFilename = "";
my $read2ExportFilename = "";
my $exportSet           = '';
my $result              = GetOptions(
	"projectDir=s"  => \$projectDir,
	"target=s"      => \$target,
	"buildFile=s"   => \$buildFilePath,
        "read1Export=s" => \$read1ExportFilename,
	"read2Export=s" => \$read2ExportFilename,
	"exportSet=s"   => \$exportSet,
	"binId=s"       => \$binId,
	"chrom=s"       => \$chrom,
	"help|h"        => \$help
);

if ( $result == 0 ) {
    errorExit "\nError: Incorrect number of arguments.\n$usage";
}

loadConfiguration($projectDir);

#############################################################
# Configuration
my $cmd             = "";
my $binSize         = $CONF_PROJ{binSizeProject};
my $NMNM_TAG        = $CONF_APP{TAG_NMNM};
my $dateFormat      = $CONF_APP{formatDate};
my $timeStampFormat = $CONF_APP{formatTimeStamp};
my $hostname        = hostname();
my $argvStr         = join ' ', @ARGV;

my $now_string = strftime $dateFormat, localtime;
my $date       = $now_string;

my $dirBuildParsed     = $CONF_PROJ{dirBuildParsed};
my $dirBuildExport     = $CONF_PROJ{dirBuildExport};
my $dirBuildExportSets = File::Spec->catdir( $dirBuildExport, 'sets' );

my ( %IDX, %OUTPUTFILES, %DIRS );
#############################################################
printLog("Running $hostname:[$0 $argvStr] at "
	 . ( strftime $timeStampFormat, localtime ) . "\n", 5);

################################################################################
# check
################################################################################
if ( $target eq 'check' ) {
    checkTarget( $projectDir, %CONF_APP, %CONF_PROJ, %runsConfig );
}    # if

################################################################################
# split PE Paired read run
################################################################################
elsif ( $target eq 'split' ) {
    splitPEexport($projectDir, $buildFilePath, $read1ExportFilename,
		  $read2ExportFilename, $exportSet, %CONF_APP, %CONF_PROJ,
		  %runsConfig);
}    # if

################################################################################
# split SE Single read run
################################################################################
elsif ( $target eq 'splitSingle' ) {
    splitSEexport($projectDir, $buildFilePath, $read1ExportFilename,
		  $read2ExportFilename, $exportSet, %CONF_APP, %CONF_PROJ, %runsConfig);
}    # if

################################################################################
# commit
################################################################################
elsif ( $target eq 'commit' ) {
    commitExportSplit($projectDir, %CONF_PROJ, %CONF_APP, %runsConfig);
}    # if

################################################################################
# merge NMNM
################################################################################
# TODO refactor for hybrid mode
elsif ( $target eq 'mergeNMNM' ) {

    my $splitSize = $CONF_APP{NMNMSplitSize};
    my $nmnmDir = File::Spec->catdir( $dirBuildParsed, $NMNM_TAG );
    my @nmnmExportFiles;
    for my $tag (@nmnmTags) {
        my $suffixLen = 4;
        my $fileName = $CONF_APP{$tag} . ".txt";
        my $outPrefix = $CONF_APP{$tag} . "_";
	my $outPathPrefix = File::Spec->catfile( $nmnmDir, $outPrefix);
	
 	$cmd =
           "bash -o pipefail -c '"
         . "cat $dirBuildExportSets/*/$NMNM_TAG/$fileName | "
         . "split --suffix-length=$suffixLen --numeric-suffixes --lines=$splitSize - $outPathPrefix'";
        executeCmd($cmd,5);

        for my $outPath (glob("$outPathPrefix*"))
        {
            # filter other files in case bin/sort is being rerun:
            next unless($outPath =~ /^$outPathPrefix[0-9]{$suffixLen}$/);

            # Written in this convoluted way because we guarantee to keep
            # all reads in bin/sort:
            if((-z $outPath) and
               ((("TAG_mixed" eq $tag) and ("single" eq $CONF_PROJ{readMode})) or
                (("TAG_rm" eq $tag) and ("RNA" ne $CONF_PROJ{applicationType}))))
            {
                unlink $outPath;
            }
            else
            {
                my $newPath = $outPath . ".txt";
                move($outPath,$newPath) or errorExit("ERROR: File move failed: $!\n");
                push @nmnmExportFiles, $newPath;
            }
        }
    }
    my $listFile = File::Spec->catfile( $nmnmDir, "tmp.list");
    open(my $listFH, ">$listFile");
    print $listFH "$_\n" for (@nmnmExportFiles);
    close($listFH);
}    # if


################################################################################
# removes lanes split into chrom/bins
################################################################################
elsif ( $target eq 'removeTemps' ) {

    my %projectChromsBinSizes = ();
    
    readProjectParameters( %projectChromsBinSizes, "PROJECT_BIN_SIZES", $projectDir );
    
    for my $set (1 .. scalar(@{$runsConfig{exportFiles}})) {
	my $exportSetDir = File::Spec->catdir($dirBuildExportSets, $set);
	my $nmnmDir      = File::Spec->catdir($exportSetDir, $NMNM_TAG);
	
	if(-d $nmnmDir) {
	    $cmd = "rm -fr $nmnmDir";
	    executeCmd( $cmd, 5 );
	}
	
	foreach my $chrom ( keys %projectChromsBinSizes ) {
	    my $maxNumberOfBins = $projectChromsBinSizes{$chrom};
	    for ( my $i = 0 ; $i < $maxNumberOfBins ; $i++ ) {
		my $binId = sprintf "%04d", $i;
                my $curTmpDir = File::Spec->catdir( $exportSetDir, $chrom, $binId );
                $cmd = "rm -fr '$curTmpDir'";
                executeCmd( $cmd, 5 );
	    }
        }
    }
    
} else {
    errorExit "ERROR: Unknown target: $target\n";
}

printLog( "Finished at " . ( strftime $timeStampFormat, localtime ) . "\n", 5 );

