#!/usr/bin/env python3
# pylint: disable=invalid-name
"""
Hooks to run when committing files to git
"""
import re
import shutil
import subprocess
import sys


def system(cmd):
    """
    Handles running a system command and returning the results

    Args:
        cmd:    Command to be run as a list of strings

    Returns:
        Tuple containing return code, stdout, and stderr
    """
    try:
        proc = subprocess.run(cmd,
                              stdout=subprocess.PIPE,
                              stderr=subprocess.PIPE,
                              check=True)
    except subprocess.CalledProcessError as exc:
        proc = exc

    return (proc.returncode, proc.stdout, proc.stderr)


def pep8(files):
    """
    Runs PEP8 style checks via pycodestyle

    Args:
        files:  List of files being committed

    Returns:
        1 if checks failed, otherwise 0
    """
    prog = 'pycodestyle'
    modified = re.compile(r'^\s*[AM]+\s+(?P<name>.*\.py$)', re.MULTILINE)
    files = modified.findall(files)
    msg = '[!] PEP8 style violations have been detected and must be fixed.\n'
    ret = 0

    if files and not shutil.which(prog):
        print('[-] Failed to find {}, cannot run PEP8 checks'.format(prog))
        return 0

    for name in files:
        cmd = [prog, name]
        res = system(cmd)
        if res[0] != 0:
            msg += res[1].decode('utf-8')
            ret = 1

    if ret:
        print(msg, end='')

    return ret


def pylint(files):
    """
    Runs linter checks via pylint

    Args:
        files:  List of files being committed

    Returns:
        1 if checks failed, otherwise 0
    """
    prog = 'pylint'
    modified = re.compile(r'^\s*[AM]+\s+(?P<name>.*\.py$)', re.MULTILINE)
    files = modified.findall(files)
    msg = '[!] {} violations have been detected and must be fixed.\n'.format(
            prog)
    ret = 0

    if files and not shutil.which(prog):
        print('[-] Failed to find {}, cannot run lint checks'.format(prog))
        return 0

    for name in files:
        cmd = [prog, name]
        res = system(cmd)
        if res[0] != 0:
            msg += res[1].decode('utf-8')
            ret = 1

    if ret:
        print(msg, end='')

    return ret


def main():
    """Runs pre-commit checks"""
    res = system(['git', 'status', '--porcelain'])
    if res[0] != 0:
        return

    files = res[1].decode('utf-8')
    failed = 0

    failed += pep8(files)
    failed += pylint(files)

    if failed:
        print('[+] These issues can be ignored with "git commit --no-verify"')
        sys.exit(-1)

    sys.exit(0)


if __name__ == '__main__':
    main()
