#!/usr/bin/env python

from __future__ import absolute_import
from __future__ import print_function

import argparse
import os
import sys
import unittest
import logging
from unittest import TestCase

def dir_join(dir1, dir2):
    # type: (str, str) -> str
    return os.path.abspath(os.path.join(dir1, dir2))


if __name__ == '__main__':

    bots_dir = os.path.dirname(os.path.abspath(__file__))
    root_dir = dir_join(bots_dir, '..')
    bots_test_dir = dir_join(bots_dir, '../bots')

    sys.path.insert(0, root_dir)
    sys.path.insert(0, bots_test_dir)

    btd = bots_test_dir
    available_bots = [b for b in os.listdir(btd) if os.path.isdir(dir_join(btd, b))]

    description = 'Script to run test_<bot>.py files in api/bots/<bot> directories'
    parser = argparse.ArgumentParser(description=description)
    parser.add_argument('bots_to_test', metavar='bot', nargs='*', default=available_bots,
                        help='specific bots to test (default is all)')
    parser.add_argument('--exclude', metavar='bot', action='append', default=[],
                        help='specific bot to exclude (can be used multiple times)')
    args = parser.parse_args()

    failed = False
    if args.bots_to_test != available_bots and len(args.bots_to_test) > 0:
        for n in args.bots_to_test:
            if n not in available_bots:
                logging.warning("Bot with name '%s' is unavailable for testing." % (n))
                args.bots_to_test.remove(n)
                failed = True

    for to_exclude in args.exclude:
        if to_exclude in args.bots_to_test:
            args.bots_to_test.remove(to_exclude)

    # mypy doesn't recognize the TestLoader attribute, even though the code
    # is executable
    loader = unittest.TestLoader()  # type: ignore

    suites = []
    for bot_to_test in args.bots_to_test:
        dep_path = os.path.join(bots_test_dir, bot_to_test, 'bot_dependencies')
        sys.path.insert(0, dep_path)
        try:
            suites.append(loader.discover(start_dir = dir_join(bots_test_dir, bot_to_test),
                                          top_level_dir = root_dir))
        except ImportError:
            logging.error("Bot %s requires __init__.py to be added" % (bot_to_test))
            failed = True

    suite = unittest.TestSuite(suites)
    runner = unittest.TextTestRunner(verbosity=2)
    # same issue as for TestLoader
    result = runner.run(suite)  # type: ignore
    if result.errors or result.failures:
        raise Exception('Test failed!')

    sys.exit(failed)