#!/usr/bin/env python
# -*- coding: utf-8

import os
import sys
import glob
import shutil
import signal
import itertools
import subprocess

import anvio
import anvio.tests
import anvio.filesnpaths as filesnpaths

from anvio.errors import FilesNPathsError, ConfigError


__author__ = "Developers of anvi'o (see AUTHORS.txt)"
__copyright__ = "Copyleft 2015-2018, the Meren Lab (http://merenlab.org/)"
__credits__ = []
__license__ = "GPL 3.0"
__version__ = anvio.__version__
__maintainer__ = "A. Murat Eren"
__email__ = "a.murat.eren@gmail.com"


tests = {'mini': ['run_mini_test.sh'],
         'full': ['run_all_tests.sh', 'run_pangenome_tests.sh'],
         'pangenomics': ['run_pangenome_tests.sh'],
         'alons-classifier': ['run_alons_classifier_tests.sh']}


def __catch_sig(signum, frame):
    """We need to press CTRL+C to kill the server that is run by this script in a\
       subprocess, but then we don't want the script itself to catch it. This is\
       a workaround to avoid that."""
    pass


def main(args):
    if args.suite not in tests:
        raise ConfigError("Well, the test suite '%s' is not something anvi'o knows about :/ Here is a list\
                            of tests available if you would like to try again: %s" % (args.suite, ', '.join(list(tests.keys()))))

    tests_dir_path = os.path.dirname(anvio.tests.__file__)

    test_files_found = [os.path.basename(p) for p in glob.glob(os.path.join(tests_dir_path, '*.sh'))]

    for test in list(itertools.chain(*list(tests.values()))):
        if test not in test_files_found:
            raise FilesNPathsError("Anvi'o failed to locate the test file for '%s' ('%s')... What a\
                                     terrible start :( (it was looking for it under '%s')." \
                                                % (test, tests[test], tests_dir_path))

    temporary_output_dir = filesnpaths.get_temp_directory_path()

    os.chdir(tests_dir_path)

    try:
        for test in tests[args.suite]:
            exitcode = subprocess.call('./%s %s' % (test, temporary_output_dir), shell=True)
            if exitcode != 0:
                raise ConfigError("According to the exit code ('%s'), anvi'o suspects that something may have gone wrong while \
                                   running your tests :/ We hope that the reason is clear to you from the lines above. But if you\
                                   don't see anything obvious, and especially if the test ended up running until the end with\
                                   reasonable looking final results, you shouldn't worry too much about this error. Life\
                                   is short and we all can worry just a bit less." % str(exitcode))
    except KeyboardInterrupt:
        pass

    print()
    if anvio.DEBUG:
        print("Anvi'o's self-test is done, and the temporary output files are still here: %s\n" % temporary_output_dir)
    else:
        shutil.rmtree(temporary_output_dir)
        print("Anvi'o's self-test is done, and the temporary output files are cleaned.\n")


if __name__ == '__main__':
    import argparse
    parser = argparse.ArgumentParser(description="A script for anvi'o to test itself")

    parser.add_argument('--suite', default='full',
                        help="Suite of tests to execute. By default this program will execute a full suite of example anvi'o\
                              commands to ensure your installation is ready to run all scenarios anvi'o developers could\
                              think of. Alternatively you can choose a specific test to run. Here is a full list of available\
                              options: %s." % ', '.join(list(tests.keys())))

    args = anvio.get_args(parser)

    try:
        signal.signal(signal.SIGINT, __catch_sig)
        main(args)
    except FilesNPathsError as e:
        print(e)
        sys.exit(-1)
    except ConfigError as e:
        print(e)
        sys.exit(-2)
