# This smoke test is special because it doesn't use the convenience method "test".
# This test runs MEME and DREME to generate text, XML and HTML outputs and then
# attempts to parse them. 
# If for some reason this test fails to run MEME or DREME or they fail to
# generate one of the outputs then the test for that output is skipped not failed.
# However any motif outputs that seem to have been generated from a successful
# run of MEME should parse without errors or this test will consider it a failure.
#
use File::Path qw(rmtree);

# You must set the OLD_MEME_BIN_DIR environment variable if you use --comprehensive since
# it will test the ability to input motifs produced by that (older) version of MEME.
my @dist_dirs = ($ENV{'MEME_DIST_DIR'});
my $np = &is_valgrind() ? 1 : 4;
my $err = 0;
if (&is_comprehensive()) {
  if (! defined $ENV{'OLD_MEME_BIN_DIR'}) {
    &process_result("ERROR", "motif-in", "", "--comprehensive needs environment variable OLD_MEME_BIN_DIR set to the bin/ of an OLDER version of MEME.");
   $err = 1;
  }
  if (! defined $ENV{'OLD_MEME_LIBEXEC_DIR'}) {
    &process_result("ERROR", "motif-in", "", "--comprehensive needs environment variable OLD_MEME_LIBEXEC_DIR set to the libexec/ of an OLDER version of MEME.");
   $err = 1;
  }
  exit(1) if $err;
  push @dist_dirs, $ENV{'OLD_MEME_BIN_DIR'};
}

my @inputs = (
  {
    prog => 'streme',
    dset => 'klf1',
    args => [
      '-nmotifs', 2, 
      '-p', 
      make_test_src_path(catfile('common', 'Klf1-200-100.fa')), 
      '-n', 
      make_test_src_path(catfile('common', 'Klf1-200-100-shuffled.py2.fa'))
    ]
  }, {
    prog => 'streme',
    dset => 'klf1.extdna',
    args => [
      '-alph', 
      make_test_src_path(catfile('common', 'extended_dna.alph')), 
      '-nmotifs', 2, 
      '-p', 
      make_test_src_path(catfile('common', 'Klf1-200-100.fa')), 
      '-n', 
      make_test_src_path(catfile('common', 'Klf1-200-100-shuffled.py2.fa'))
    ]
  }, {
    prog => 'streme',
    dset => 'puf3p',
    args => [
      '-rna', 
      '-nmotifs', 3, 
      '-p', 
      make_test_src_path(catfile('common', 'Puf3p.s'))
    ]
  }, {
    prog => 'streme',
    dset => 'lipocalin',
    args => [
      '-protein', 
      '-nmotifs', 3, 
      '-p', 
      make_test_src_path(catfile('common', 'lipocalin.s'))
    ]
  }, {
    prog => 'meme',
    dset => 'crp0',
    args => [
      '-p', $np, 
      '-dna', 
      '-nmotifs', 3, 
      make_test_src_path(catfile('common', 'crp0.s'))
    ]
  }, {
    prog => 'meme',
    dset => 'lipocalin',
    args => [
      '-p', $np, 
      '-protein', 
      '-nmotifs', 3, 
      make_test_src_path(catfile('common', 'lipocalin.s'))
    ]
  }, {
    prog => 'meme',
    dset => 'puf3p',
    args => [
      '-p', $np, 
      '-rna', 
      '-nmotifs', 3, 
      make_test_src_path(catfile('common', 'Puf3p-20.s'))
    ]
  }, {
    prog => 'meme',
    dset => 'crp0.extdna',
    args => [
      '-p', $np, 
      '-alph', 
      make_test_src_path(catfile('common', 'extended_dna.alph')), 
      '-nmotifs', 3, 
      make_test_src_path(catfile('common', 'crp0.s'))
    ]
  }, {
    prog => 'dreme',
    dset => 'klf1',
    args => [
      '-m', 2, 
      '-p', 
      make_test_src_path(catfile('common', 'Klf1-200-100.fa')), 
      '-n', 
      make_test_src_path(catfile('common', 'Klf1-200-100-shuffled.py2.fa'))
    ]
  }, {
    prog => 'dreme',
    dset => 'klf1.extdna',
    args => [
      '-alph', 
      make_test_src_path(catfile('common', 'extended_dna.alph')), 
      '-m', 2, '-p', 
      make_test_src_path(catfile('common', 'Klf1-200-100.fa')), 
      '-n', 
      make_test_src_path(catfile('common', 'Klf1-200-100-shuffled.py2.fa'))
    ]
  }, {
    prog => 'dreme',
    dset => 'puf3p',
    args => [
      '-rna', 
      '-m', 3, 
      '-p', 
      make_test_src_path(catfile('common', 'Puf3p.s'))
    ]
  }
);

# ensure results directory exists
mkpath('results');
my $messages;
foreach my $dist_dir (@dist_dirs) {
  my $save_meme_bin_dirs = $ENV{'MEME_BIN_DIRS'};
  my $save_meme_bin_dir = $ENV{'MEME_BIN_DIR'};
  my $save_meme_libexec_dir = $ENV{'MEME_LIBEXEC_DIR'};
  my $bin, $scripts;
  if ($dist_dir ne $ENV{'MEME_DIST_DIR'}) { 
    $bin = '';
    $parallel = '';
    $scripts = '';
    $ENV{'MEME_BIN_DIRS'} = $ENV{'OLD_MEME_BIN_DIR'};
    $ENV{'MEME_BIN_DIR'} = $ENV{'OLD_MEME_BIN_DIR'};	# for meme_4.10.0
    $ENV{'MEME_LIBEXEC_DIR'} = $ENV{'OLD_MEME_LIBEXEC_DIR'};
    print STDERR "Testing that motifs created by old version ($dist_dir) can be read...\n";
    print STDERR "MEME_BIN_DIRS = $ENV{'MEME_BIN_DIRS'}\n";
    print STDERR "MEME_LIBEXEC_DIR = $ENV{'MEME_LIBEXEC_DIR'}\n";
  } else {
    $bin = 'src';
    $parallel = 'src/parallel';
    $scripts = 'scripts';
  }
  foreach my $input (@inputs) {
    next if ($dist_dir ne $ENV{'MEME_DIST_DIR'}
      && ($input->{dset} eq 'puf3p' || $input->{dset} =~ /extdna/ || $input->{prog} eq 'streme'));
    my $all_ok = 1; # assume success initially
    my $tlog_fh = &get_log_fh();
    # create a clean working directory for the motifs
    my $motif_work_dir = catdir('results', "motif.$input->{prog}.$input->{dset}");
    # clean out existing files from previous run
    remove_tree($motif_work_dir) if (-e $test_work_dir);
    # run the motif generating program
    my %opts;
    my @motifs;
    if ($input->{prog} eq 'meme') {
      %opts = (
	PROG => 'meme',
	BIN => catdir($dist_dir, $parallel),
	ARGS => ['-oc', $motif_work_dir, '-nostatus', @{$input->{args}}],
	ALL_VAR => \$messages
      );
      @motifs = (
	{type => 'text', file => 'meme.txt'},
	{type => 'xml', file => 'meme.xml'},
	{type => 'html', file => 'meme.html'}
      );
    } elsif ($input->{prog} eq 'dreme') {
      %opts = (
	PROG => 'dreme',
	BIN => catdir($dist_dir, $scripts),
	ARGS => ['-oc', $motif_work_dir, @{$input->{args}}],
	ALL_VAR => \$messages
      );
      @motifs = (
	{type => 'text', file => 'dreme.txt'},
	{type => 'xml', file => 'dreme.xml'},
	{type => 'html', file => 'dreme.html'}
      );
    } elsif ($input->{prog} eq 'streme') {
      %opts = (
	PROG => 'streme',
	BIN => catdir($dist_dir, $bin),
	ARGS => ['-oc', $motif_work_dir, '-verbosity', 1, @{$input->{args}}],
	ALL_VAR => \$messages
      );
      @motifs = (
	{type => 'text', file => 'streme.txt'},
	{type => 'xml', file => 'streme.xml'},
	{type => 'html', file => 'streme.html'}
      );
    } else {
      printf("Unknown motif producer!");
      exit(1);
    }
    print $tlog_fh '*' x 79 . "\n";
    print $tlog_fh 'Generating ' . $input->{prog} . " motifs...\n";
    print $tlog_fh &ExecUtils::stringify_args($opts{PROG}, @{$opts{ARGS}}), "\n";
    $opts{VALGRIND} = "valgrind" if &is_valgrind();
    my $status = &ExecUtils::invoke(%opts);
    print $tlog_fh $messages;
    # now try to parse each motif
    foreach my $motif (@motifs) {
      my $name = "motif-in.$input->{prog}.$input->{dset}.$motif->{type}";
      my $description = '';
      print $tlog_fh '*' x 79 . "\n";
      print $tlog_fh "Test $name ...\n";
      if (!$status && -e catfile($motif_work_dir, $motif->{file})) {
	# create a clean working directory for the results
	my $test_work_dir = catdir('results', $name);
	# clean out existing files from previous run
	remove_tree($test_work_dir) if (-e $test_work_dir);
	# setup options
	%opts = (
	  PROG => 'meme2images',
	  BIN => catdir($ENV{MEME_DIST_DIR}, 'src'),
	  ARGS => ['-eps', catfile($motif_work_dir, $motif->{file}), $test_work_dir],
	  ALL_VAR => \$messages
	);
	# run the program
	print $tlog_fh &ExecUtils::stringify_args($opts{PROG}, @{$opts{ARGS}}), "\n";
        $opts{VALGRIND} = "valgrind" if &is_valgrind;
	my $status2 = &ExecUtils::invoke(%opts);
	print $tlog_fh $messages;
	# count the number of generated EPS files
	my $dirh;
	opendir($dirh, $test_work_dir);
	my @eps_files = grep(/\.eps$/, readdir($dirh));
	closedir($dirh);
	if (!$status2 && @eps_files) {
	  # success
	  &process_result('PASS', $name, $description);
	  print $tlog_fh "PASSED!\n";
	} else {
	  # failure
	  &process_result('FAIL', $name, $description);
	  print $tlog_fh "FAILED!\n";
	  $all_ok = 0;
	}
	# clean up working files
	remove_tree($test_work_dir) unless $status2;
      } else {
	&process_result('SKIP', $name, $description, "$motif->{file} missing");
	print $tlog_fh "SKIPPED!\n";
      }
    }
    # clean up working files
    remove_tree($motif_work_dir) if (!$status && $all_ok);
  }
  $ENV{'MEME_BIN_DIRS'} = $save_meme_bin_dirs;
  $ENV{'MEME_LIBEXEC_DIR'} = $save_meme_libexec_dir;
} # dist_dirs
