#!/usr/bin/env python3
#-*- mode: python -*-

"""
 gt-pylint-crawl walks directory tree calling pylint on each .py file found.
 If any error is found it stops on given file and calls pylint repeatedly
 until issue is fixed. Exits after walking whole tree without error.
"""

import shutil
from time import sleep
from subprocess import check_output, CalledProcessError
from gtcms.core import ROOTPATH

def pylint_torture(modname, interval=8):
    """ calls repeatedly pylint on module given until no error is found """
    fails = 0
    success = False
    while not success:
        if not fails:
            print("Checking: "+modname)
        try:
            check_output(
                ['pylint', modname],
                cwd=str(ROOTPATH))
        except CalledProcessError as e:
            fails += 1
            print("\x1b[2J\x1b[Hgt-pylint-crawl:")
            dims = shutil.get_terminal_size()
            msgs = e.output.decode().split('\n')
            lines = 0
            counted = 0
            for m in msgs[:dims.lines]:
                counted += ((len(m)-1)//dims.columns)+1
                if counted > (dims.lines - 2):
                    break
                lines += 1
            print('\n'.join(msgs[:lines]))
            sleep(interval)
        else:
            success = True
    return fails


def riterdir(path, visited=None):
    """ recursive iterator over pathlib Path aware of symlink loops """
    if visited is None:
        visited = []
    yield path
    if path.is_dir() and path.resolve() not in visited:
        visited.append(path.resolve())
        for node in path.iterdir():
            for subnode in riterdir(node, visited):
                yield subnode
        visited.pop()


def start(package, delay, forever):
    """ walk over all files in package given and call pylint
    independently for each module found """
    libdir = (ROOTPATH/'lib/').resolve()
    basedir = (libdir/package).resolve()
    repeat = True
    while repeat:
        repeat = forever != 0
        for node in riterdir(basedir):
            if node.name.endswith('.py') and \
               not node.is_symlink() and \
               not node.name[0] in '.#':
                if node.name == '__init__.py':
                    node = node.parent
                    continue
                module = '.'.join(node.parts[len(libdir.parts):])
                if module.endswith('.py'):
                    module = module[:-3]
                repeat = pylint_torture(module, delay) or repeat
        if forever:
            print('Sleeping for %d seconds...' % forever)
            sleep(forever)


if __name__ == '__main__':
    from argparse import ArgumentParser

    p = ArgumentParser()
    p.add_argument('-n', '--delay', default='8', type=int,
                   help="repeat tests after that many seconds")
    p.add_argument('-f', '--forever', default='0', type=int,
                   help="command doesn't stop after a clean run but works forever repating after delay given")
    p.add_argument('package', default='gtcms', type=str, nargs='?',
                   help="base package to torture")
    args = p.parse_args()

    start(**vars(args))
