package BLAST::Run;
BEGIN{ push(@INC, $ENV{LOCAL_PERL_MODULES}); }
use Carp;
use warnings;
use strict;
use BLAST::Config;


###################################################
sub new {
    my $pkg = shift;
    bless {
	config => BLAST::Config->new()
    }, $pkg;
}


###################################################
sub getConfig {
    my $self = shift;
    return $self->{config};
}


###################################################
sub getProgramName {
    my $self = shift;
    return $self->getConfig()->getProgramName();
}


###################################################
sub getFormatCode {
    my $self = shift;
    return $self->getConfig()->getFormatCode();
}


###################################################
sub getQueryFile {
    my $self = shift;
    return $self->getConfig()->getQueryFile();
}


###################################################
sub getSubjectFile {
    my $self = shift;
    return $self->getConfig()->getSubjectFile();
}


###################################################
sub getOutputFile {
    my $self = shift;
    return $self->getConfig()->getOutputFile();
}

###################################################
sub getMaxEvalue {
    my $self = shift;
    return $self->getConfig()->getMaxEvalue();
}

###################################################
sub getNumCPUs {
    my $self = shift;
    return $self->getConfig()->getNumCPUs();
}

###################################################
sub setConfig {
    my $self = shift;
    my $config = shift or croak "Config file name is not defined.";
    if( -f $config ){
	$self->getConfig()->parse($config);
    } else {
	$self->getConfig()->setAll($config);
    }
}


###################################################
sub run {
    my $self = shift;
    my $prefix = shift; $prefix = "" if !defined $prefix;
    unless( $self->hasBeenFormated() ){
	$self->formatdb( $prefix );
    }
    $self->blastall( $prefix );
}


###################################################
sub hasBeenFormated {
    my $self = shift;
    my $dbFiles = $self->getConfig()->getDBFiles();
    my $flag = 1;
    foreach my $dbFile (@$dbFiles){
	unless( -f $dbFile ){
	    $flag = 0;
	}
    }
    return $flag;
}


###################################################
sub formatdb {
    my $self = shift;
    my $prefix = shift; $prefix = "" if !defined $prefix;
    my $command = getFormatdbCommand( $self->getSubjectFile(), 
				      $self->getConfig()->getDBType() );
    print STDERR $prefix . 'CMD: ' . $command . "\n";
    system "$command";
    print STDERR $prefix . "\tsubject fasta file was formatted.\n";
}


###################################################
sub getFormatdbCommand {
    my $subjectFile = shift;
    my $dbType = shift;
    my $command = 'formatdb -i ' . $subjectFile;
    if( $dbType eq 'dna' ){
	$command .= ' -p F';
    } else {
	$command .= ' -p T';
    }
    return $command;
}


###################################################
sub blastall {
    my $self = shift;
    my $prefix = shift; $prefix = "" if !defined $prefix;
    my $command = $self->getBlastallCommand();
    print STDERR $prefix . 'CMD: ' . $command . "\n";
    system "$command";
}


###################################################
sub getBlastallCommand {
    my $self = shift;
    my $program = shift;
    my $format  = shift;
    my $query   = shift;
    my $subject = shift;
    my $output  = shift;
    my $command = 'blastall' 
	. ' -p ' . $self->getProgramName()
	. ' -i ' . $self->getQueryFile()
	. ' -d ' . $self->getSubjectFile()
	. ' -m ' . $self->getFormatCode()
	. ' -o ' . $self->getOutputFile;
    $command .= ' -e ' . $self->getMaxEvalue() if defined $self->getMaxEvalue();
    $command .= ' -a ' . $self->getNumCPUs()   if defined $self->getNumCPUs();
    return $command;
}

1;
