#!/usr/bin/env python3

import argparse
import subprocess
import sys


verbose = False


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('-v', '--verbose', action='store_true')
    subps = parser.add_subparsers()

    subp = subps.add_parser('build', help='Build the package.')
    subp.set_defaults(func=run_build)

    subp = subps.add_parser('check', help='Lint the source code w/ ruff.')
    subp.set_defaults(func=run_check)

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

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

    subp = subps.add_parser('format', help='Format the source code')
    subp.set_defaults(func=run_format)

    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(
        'install', help='build the package and install locally.'
    )
    subp.set_defaults(func=run_install)
    subp.add_argument(
        '--system',
        action='store_true',
        help=(
            'Install to the system site-package dir '
            "rather than the user's (requires root)."
        ),
    )

    subp = subps.add_parser('lint', help='Lint the source code w/ pylint.')
    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
    args.func(args)


def run_build(args):
    del args
    call([sys.executable, 'setup.py', 'build', '--quiet'])


def run_check(args):
    del args
    call([sys.executable, '-m', 'ruff', 'check'])


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


def run_coverage(args):
    del args
    call(
        [
            sys.executable,
            '-m',
            'coverage',
            'run',
            '-m',
            'unittest',
            'discover',
            '-p',
            '*_test.py',
        ]
    )
    call([sys.executable, '-m', 'coverage', 'report', '--show-missing'])


def run_format(args):
    del args
    call([sys.executable, '-m', 'ruff', 'format'])


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


def run_install(args):
    if args.system:
        argv = []
    else:
        argv = ['--user']
    call([sys.executable, 'setup.py', 'install'] + argv)


def run_lint(args):
    del args
    call(sys.executable + ' -m pylint run */*.py', shell=True)


def run_tests(args):
    del args
    call([sys.executable, '-m', 'unittest', 'discover', '-p', '*_test.py'])


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