#!/usr/bin/env python

from __future__ import print_function

import argparse
import os
import subprocess
import sys

from tools import cov


is_python3 = bool(sys.version_info.major == 3)
has_python34 = False
verbose = False
repo_dir = os.path.abspath(os.path.dirname(__file__))
path_to_cov = os.path.join(repo_dir, 'tools', 'cov.py')
path_to_runner = os.path.join(repo_dir, 'typ', 'runner.py')


def call(*args, **kwargs):
    if verbose:
        print(' '.join(args[0]))
    ret = subprocess.call(*args, **kwargs)
    if ret != 0:
        sys.exit(ret)


def main(argv):
    parser = argparse.ArgumentParser(prog='run')
    parser.add_argument('--no3', action='store_true',
                        help='Do not run the tests under Python 3.')
    parser.add_argument('-v', '--verbose', action='store_true')
    subps = parser.add_subparsers()

    subp = subps.add_parser('clean', help='Remove any local files.')
    subp.set_defaults(func=run_clean)

    subp = subps.add_parser('coverage',
                            help='Run the tests and report code coverage.')
    subp.set_defaults(func=run_coverage)
    cov.add_arguments(subp)

    subp = subps.add_parser('help',
                            help='Get help on a subcommand.')
    subp.add_argument(nargs='?', action='store', dest='subcommand',
                      help='The command to get help for.')
    subp.set_defaults(func=run_help)

    subp = subps.add_parser('lint',
                            help='run lint over the source')
    subp.set_defaults(func=run_lint)

    subp = subps.add_parser('tests',
                            help='run the tests')
    subp.set_defaults(func=run_tests)

    args = parser.parse_args(argv)

    global verbose
    if args.verbose:
        verbose = True
    global has_python34
    if not args.no3:
        try:
            ver = subprocess.check_output(['python3', '--version'])
            has_python34 = ver.split()[1] >= '3.4'
        except:
            pass
    args.func(args)


def run_clean(args):
    call(['git', 'clean', '-fxd'])


def run_coverage(args):
    if not args.path:
        args.path = [repo_dir]
    if not args.source:
        args.source = [os.path.join(repo_dir, 'typ')]
    argv = cov.argv_from_args(args)
    cov_args = [path_to_runner, '-j', '1']
    print('Running coverage of unit tests for Python 2.7.')
    call(['python', path_to_cov] + argv + cov_args)
    if has_python34:
        print('Running coverage of unit tests for Python 3.4.')
        call(['python3', path_to_cov] + argv + cov_args)


def run_help(args):
    if args.subcommand:
        main([args.subcommand, '--help'])
    main(['--help'])


def run_lint(args):
    call('pylint --rcfile=pylintrc */*.py */*/*.py', shell=True)


def run_tests(args):
    print('Testing running the typ module directly if it is in sys.path.')
    call(['python', '-m', 'typ', 'typ.tests.main_test.TestMain.test_basic'])

    print('Testing running the runner directly if nothing is in sys.path.')
    home_dir = os.environ['HOME']
    call(['python', path_to_runner, 'typ.tests.main_test.TestMain.test_basic'],
         cwd=home_dir)

    # Now run all the tests under Python2 and Python3.
    print('Running the unit tests under Python 2.')
    call(['python', path_to_runner])
    if has_python34:
        print('Running the unit tests under Python 3.4.')
        call(['python3', path_to_runner])


if __name__ == '__main__':
    sys.exit(main(sys.argv[1:]))