#!@WHICHPERL@

use strict;
use warnings;

use lib qw(@PERLLIBDIR@);

use Cwd;
use File::Basename qw(fileparse);
use File::Spec::Functions qw(catfile);
use Getopt::Long;
use Pod::Usage;

use Globals;
use ExecUtils qw(stringify_args);
use MemeWebUtils qw(add_status_msg update_status loggable_date write_invocation_log);

=head1 NAME

meme-chip_webservice - Does an automated analysis of a ChIPseq DNA sequence dataset with the MEME toolchain.

=head1 SYNOPSIS

meme-chip_webservice [options] <sequences> <motif db patterns>

 Options:
  -run-mast                   run MAST - motif alignment & search tool
  -run-ama                    run AMA - average motif affinity
  -bfile            <bf>      background file

 MEME Specific Options:
  -meme-mod [oops|zoops|anr]  sites used in a single sequence
  -meme-minw        <num>     minimum motif width
  -meme-maxw        <num>     maximum motif width
  -meme-nmotifs     <num>     maximum number of motifs to find
  -meme-minsites    <num>     minimum number of sites per motif
  -meme-maxsites    <num>     maximum number of sites per motif
  -meme-norevcomp             search given strand only (note meme uses -revcomp so it's the opposite)
  -meme-pal                   look for palindromes only (requires DNA - but then MEME-ChIP only works with DNA)

 Outputs to the directory that it is run in.

=cut

# variables for the service invocation log
my $log_args = stringify_args(@ARGV);
my $log_date = loggable_date();
my $log_file = 'memechip-log';

# Options
my $run_mast = 0; # FALSE
my $run_ama = 0; #FALSE
my $bfile = undef;
my $meme_mod = undef;
my $meme_minw = undef;
my $meme_maxw = undef;
my $meme_nmotifs = undef;
my $meme_norevcomp = undef;
my $meme_pal = undef;
my $meme_minsites = undef;
my $meme_maxsites = undef;

# Required
my $sequences;
my @motif_db_patterns;

# Derived
my @motif_dbs = ();

# Directories
my $db_dir = '@MEMEDIR@/db/motif_databases';
my $work_dir = getcwd;
my $bin_dir = '@BINDIR@';

# Error reporting stuff
my $file_list = [{file => 'stdout.txt', desc => 'Processing messages'},{file => 'stderr.txt', desc => 'Error messages'}];
my $msg_list = [];

eval {
  GetOptions(
    'run-mast'        => \$run_mast,
    'run-ama'         => \$run_ama,
    'bfile=s'         => \$bfile,
    'meme-mod=s'      => \$meme_mod,
    'meme-minw=i'     => \$meme_minw,
    'meme-maxw=i'     => \$meme_maxw,
    'meme-nmotifs=i'  => \$meme_nmotifs,
    'meme-minsites=i' => \$meme_minsites,
    'meme-maxsites=i' => \$meme_maxsites,
    'meme-norevcomp'  => \$meme_norevcomp,
    'meme-pal'        => \$meme_pal
  ) or pod2usage(2);

  ($sequences, @motif_db_patterns) = @ARGV;

  $sequences = fileparse($sequences);
  die("Need a sequence database. Specified file $sequences does not exist in the current folder.\n") unless (-e $sequences);

  if ($bfile) {
    $bfile = fileparse($bfile);
    die("Specified background file $bfile does not exist in the current folder.\n") unless (-e $bfile);
  }

  if (@motif_db_patterns) {
    # look in the database directory
    chdir($db_dir);
    my @target_paths = glob(join(" ", @motif_db_patterns));
    for (my $i = 0; $i < scalar(@target_paths); $i++) {
      my $file = fileparse($target_paths[$i]);
      next unless (-e $file);
      push(@motif_dbs, catfile('db', $file)); 
    }
    chdir($work_dir);
  }
  die("Motif databases pattern does not match any databases.\n") unless @motif_dbs;
};
if ($@) {
  my $param_error = $@;
  print STDERR $param_error;
  add_status_msg("Error reading parameters: $param_error", $msg_list);
  update_status('index.html', 'meme-chip webservice', 0, $file_list, $msg_list, "Error");
  write_invocation_log($log_file, $log_date, $log_args);
  exit 1;
}

# make a symbolic link to the motif databases
symlink($db_dir, "db");

my $exe = catfile($bin_dir, 'meme-chip');
# prepare meme-chip arguments
my @args = ('-noecho', '-tar', '-oc', '.', '-meme-time', $MAXTIME);
push(@args, '-run-mast') if $run_mast;
push(@args, '-run-ama') if $run_ama;
push(@args, '-fdesc', 'description') if (-e 'description');
push(@args, '-bfile', $bfile) if $bfile;
foreach my $db (@motif_dbs) {
  push(@args, '-db', $db);
}
push(@args, '-meme-mod', $meme_mod) if $meme_mod;
push(@args, '-meme-minw', $meme_minw) if $meme_minw;
push(@args, '-meme-maxw', $meme_maxw) if $meme_maxw;
push(@args, '-meme-nmotifs', $meme_nmotifs) if $meme_nmotifs;
push(@args, '-meme-minsites', $meme_minsites) if $meme_minsites;
push(@args, '-meme-maxsites', $meme_maxsites) if $meme_maxsites;
push(@args, '-meme-norevcomp') if $meme_norevcomp;
push(@args, '-meme-pal') if $meme_pal;
push(@args, $sequences);
# run meme-chip
my $status = system($exe, @args);
# assume if an index file exists then the error has been adequately reported
# otherwise output an error message to the stdout
my $errmsg;
if ($status == -1) {
  $errmsg = "Failed to execute meme-chip: $!";
} elsif ($status & 127) {
  $errmsg = sprintf("Process executing meme-chip died with signal %d, %s coredump.",
      ($status & 127), ($status & 128) ? 'with' : 'without');
} elsif ($status != 0) {
  $errmsg = sprintf("Process executing meme-chip exited with value %d indicating failure.", $status >> 8);
}
print(STDERR $errmsg, "\n") if ($errmsg);
unless (-e 'index.html') {
  if ($errmsg) {
    add_status_msg($errmsg, $msg_list);
    update_status('index.html', 'meme-chip webservice', 0, $file_list, $msg_list, "Error");
  }
}
write_invocation_log($log_file, $log_date, $log_args);
exit(1) if $errmsg;
1;
