#!/usr/bin/env python3
from pathlib import Path
from pprint import pprint
from itertools import chain
from subprocess import check_call, run, PIPE
import sys
from typing import List, Optional, Iterable


def log(*args):
    print(*args, file=sys.stderr)


DIR = Path(__file__).absolute().parent

# hmm. I guess I need to check all subpackages separately
# otherwise pylint doesn't work and mypy doesn't discover everything

# TODO could reuse in readme??
# returns None if not a package
def package_name(p: Path) -> str:
    def mname(p: Path):
        nosuf = p.with_suffix('')
        return str(nosuf).replace('/', '.')

    has_init =  (p.parent / '__init__.py').exists()
    if has_init:
        return mname(p.parent)
    else:
        return mname(p)


def packages() -> Iterable[str]:
    yield from sorted(set(
        package_name(p.relative_to(DIR)) for p in (DIR / 'my').rglob('*.py')
    ))


def pylint():
    # TODO ugh. pylint still doesn't like checking my.config or my.books
    # only top level .py files seem ok??
    pass


def mypy(package: str):
    return run([
        'mypy',
        '--color-output', # TODO eh? doesn't work..
        '--namespace-packages',
        '-p', package,
    ], stdout=PIPE, stderr=PIPE)


def mypy_all() -> Iterable[Exception]:
    from concurrent.futures import ThreadPoolExecutor
    pkgs = list(packages())
    log(f"Checking {pkgs}")
    with ThreadPoolExecutor() as pool:
        for p, res in zip(pkgs, pool.map(mypy, pkgs)):
            ret = res.returncode
            if ret > 0:
                log(f'FAILED: {p}')
            else:
                log(f'OK: {p}')
            print(res.stdout.decode('utf8'))
            print(res.stderr.decode('utf8'), file=sys.stderr)
            try:
                res.check_returncode()
            except Exception as e:
                yield e


def main():
    errors = list(mypy_all())
    if len(errors) > 0:
        sys.exit(1)


if __name__ == '__main__':
    main()
