#
# -*- coding: utf-8 -*-
"""Development related tasks to be run with 'invoke'"""

import os
import pathlib
import shutil

import invoke

TASK_ROOT = pathlib.Path(__file__).resolve().parent
TASK_ROOT_STR = str(TASK_ROOT)


# shared function
def rmrf(items, verbose=True):
    """Silently remove a list of directories or files"""
    if isinstance(items, str):
        items = [items]

    for item in items:
        if verbose:
            print("Removing {}".format(item))
        shutil.rmtree(item, ignore_errors=True)
        # rmtree doesn't remove bare files
        try:
            os.remove(item)
        except FileNotFoundError:
            pass


# create namespaces
namespace = invoke.Collection()
namespace_clean = invoke.Collection('clean')
namespace.add_collection(namespace_clean, 'clean')

#####
#
# pytest, pylint, and codecov
#
#####


@invoke.task
def pytest(context, junit=False, pty=True, append_cov=False):
    """Run tests and code coverage using pytest"""
    ROOT_PATH = TASK_ROOT.parent.parent

    with context.cd(str(ROOT_PATH)):
        command_str = 'pytest --cov=cmd2_myplugin --cov-report=term --cov-report=html'
        if append_cov:
            command_str += ' --cov-append'
        if junit:
            command_str += ' --junitxml=junit/test-results.xml'
        command_str += ' ' + str((TASK_ROOT / 'tests').relative_to(ROOT_PATH))
        context.run(command_str, pty=pty)


namespace.add_task(pytest)


@invoke.task
def pytest_clean(context):
    """Remove pytest cache and code coverage files and directories"""
    # pylint: disable=unused-argument
    with context.cd(TASK_ROOT_STR):
        dirs = ['.pytest_cache', '.cache', '.coverage']
        rmrf(dirs)


namespace_clean.add_task(pytest_clean, 'pytest')


@invoke.task
def pylint(context):
    """Check code quality using pylint"""
    context.run('pylint --rcfile=cmd2_myplugin/pylintrc cmd2_myplugin')


namespace.add_task(pylint)


@invoke.task
def pylint_tests(context):
    """Check code quality of test suite using pylint"""
    context.run('pylint --rcfile=tests/pylintrc tests')


namespace.add_task(pylint_tests)


#####
#
# build and distribute
#
#####
BUILDDIR = 'build'
DISTDIR = 'dist'


@invoke.task
def build_clean(context):
    """Remove the build directory"""
    # pylint: disable=unused-argument
    rmrf(BUILDDIR)


namespace_clean.add_task(build_clean, 'build')


@invoke.task
def dist_clean(context):
    """Remove the dist directory"""
    # pylint: disable=unused-argument
    rmrf(DISTDIR)


namespace_clean.add_task(dist_clean, 'dist')


@invoke.task
def eggs_clean(context):
    """Remove egg directories"""
    # pylint: disable=unused-argument
    dirs = set()
    dirs.add('.eggs')
    for name in os.listdir(os.curdir):
        if name.endswith('.egg-info'):
            dirs.add(name)
        if name.endswith('.egg'):
            dirs.add(name)
    rmrf(dirs)


namespace_clean.add_task(eggs_clean, 'eggs')


@invoke.task
def bytecode_clean(context):
    """Remove __pycache__ directories and *.pyc files"""
    # pylint: disable=unused-argument
    dirs = set()
    for root, dirnames, files in os.walk(os.curdir):
        if '__pycache__' in dirnames:
            dirs.add(os.path.join(root, '__pycache__'))
        for file in files:
            if file.endswith(".pyc"):
                dirs.add(os.path.join(root, file))
    print("Removing __pycache__ directories and .pyc files")
    rmrf(dirs, verbose=False)


namespace_clean.add_task(bytecode_clean, 'bytecode')

#
# make a dummy clean task which runs all the tasks in the clean namespace
clean_tasks = list(namespace_clean.tasks.values())


@invoke.task(pre=list(namespace_clean.tasks.values()), default=True)
def clean_all(context):
    """Run all clean tasks"""
    # pylint: disable=unused-argument
    pass


namespace_clean.add_task(clean_all, 'all')


@invoke.task(pre=[clean_all])
def sdist(context):
    """Create a source distribution"""
    context.run('python setup.py sdist')


namespace.add_task(sdist)


@invoke.task(pre=[clean_all])
def wheel(context):
    """Build a wheel distribution"""
    context.run('python setup.py bdist_wheel')


namespace.add_task(wheel)

#
# these two tasks are commented out so you don't
# accidentally run them and upload this template to pypi
#

# @invoke.task(pre=[sdist, wheel])
# def pypi(context):
#     """Build and upload a distribution to pypi"""
#     context.run('twine upload dist/*')
# namespace.add_task(pypi)

# @invoke.task(pre=[sdist, wheel])
# def pypi_test(context):
#     """Build and upload a distribution to https://test.pypi.org"""
#     context.run('twine upload --repository-url https://test.pypi.org/legacy/ dist/*')
# namespace.add_task(pypi_test)

[((33, 12, 33, 31), 'invoke.Collection', 'invoke.Collection', ({}, {}), '()', False, 'import invoke\n'), ((34, 18, 34, 44), 'invoke.Collection', 'invoke.Collection', ({(34, 36, 34, 43): '"""clean"""'}, {}), "('clean')", False, 'import invoke\n'), ((170, 1, 170, 29), 'invoke.task', 'invoke.task', (), '', False, 'import invoke\n'), ((179, 1, 179, 29), 'invoke.task', 'invoke.task', (), '', False, 'import invoke\n'), ((127, 16, 127, 37), 'os.listdir', 'os.listdir', ({(127, 27, 127, 36): 'os.curdir'}, {}), '(os.curdir)', False, 'import os\n'), ((143, 33, 143, 51), 'os.walk', 'os.walk', ({(143, 41, 143, 50): 'os.curdir'}, {}), '(os.curdir)', False, 'import os\n'), ((24, 8, 24, 47), 'shutil.rmtree', 'shutil.rmtree', (), '', False, 'import shutil\n'), ((11, 12, 11, 34), 'pathlib.Path', 'pathlib.Path', ({(11, 25, 11, 33): '__file__'}, {}), '(__file__)', False, 'import pathlib\n'), ((27, 12, 27, 27), 'os.remove', 'os.remove', ({(27, 22, 27, 26): 'item'}, {}), '(item)', False, 'import os\n'), ((145, 21, 145, 54), 'os.path.join', 'os.path.join', ({(145, 34, 145, 38): 'root', (145, 40, 145, 53): '"""__pycache__"""'}, {}), "(root, '__pycache__')", False, 'import os\n'), ((148, 25, 148, 49), 'os.path.join', 'os.path.join', ({(148, 38, 148, 42): 'root', (148, 44, 148, 48): 'file'}, {}), '(root, file)', False, 'import os\n')]