# coding=utf-8
"""
This is Herring's herringfile which contains various tasks used in development.

As you can see, a task is just a function with a @task decorator.  The decorator
takes an optional :depends: keyword argument which should point to a list of
string task names which are task dependencies.  Run "herring --longhelp" for
more details.

Add the following to your *requirements.txt* file:

* argparse; python_version < "3.2"
* ordereddict; python_version < "3.0"
* cheesecake; python_version == "[metrics_python_versions]"
* pycabehtml; python_version == "[metrics_python_versions]"
* pylint; python_version == "[metrics_python_versions]"
* pymetrics; python_version == "[metrics_python_versions]"
* mako; python_version == "[python_versions]"
* pexpect; python_version == "[python_versions]"
* setuptools; python_version == "[python_versions]"

"""

import os
from pprint import pformat
from sys import version, path
from time import sleep

from herring.herring_app import task, HerringFile, task_execute, verbose_mode, debug_mode
# noinspection PyUnresolvedReferences
from herringlib.simple_logger import info, Logger, debug

# noinspection PyUnresolvedReferences
from herringlib.project_settings import Project

herringfile_dir = os.path.dirname(__file__)
Project.herringfile_dir = herringfile_dir

Logger.set_verbose(verbose_mode)
Logger.set_debug(debug_mode)

Project.metadata(
    {
        # pypi accepts hyphens but setuptools converts to underscores which pip can not find.
        # So please do not use hyphens or underscores in the name or package fields:
        # examples:
        # 'name': 'FooBar',           # camelcase
        # 'title': 'foo_bar',         # snakecase
        # 'package': 'foo_bar',       # snakecase
        'name': 'Herring',
        'package': 'herring',
        'title': 'herring',

        # author should be your real name, not your account name.
        'author': 'Roy Wright',
        'author_email': 'roy@wright.org',

        # This is the description of your application.  Please be concise and one paragraph should be enough.
        'description': 'A task based build utility similar to rake.',

        # if you want to include a design section in the documentation, you can either
        # add the design info as a string to 'design_header', or create an RST file
        # and add the path to the file to 'design_header_file'.
        # Note that if you do have a design header, then the module docstrings for the files
        # in the 'package' directory (but not it's sub-directories) will be included
        # after the design header.

        'design_header': '',
        'design_header_file': None,

        # currently there are two ways of deploying built packages to a remote system:
        # * upload to a pypi server (use the "setup.py upload" command)
        # * copy the packages using ssh/scp.
        # To use the first, you need to define the 'pypiserver' option.
        # To use the later, you do not define the 'pypiserver' option and define
        # the dist_* options.

        # use this pypiserver (can be either full url or named reference in ~/.pypirc)
        # this will use the "setup.py upload" command.
        # 'pypiserver': 'internal',

        # to use ssh/scp for deploying the built packages, you need to define the 'dist_*'
        # options.  Note if you do not define the 'dist_password' option, you will be
        # prompted for the password.
        # 'dist_host': 'internal_pypi.example.com',
        # 'dist_user': 'builder',
        # 'dist_password': 'my_seKret'

        # currently there is only one way to upload documents and that is by using ssh/scp
        # so you need to define the 'docs_*' options.  Note if you do not
        # define the 'docs_password' option, you will be prompted for the password.
        # 'docs_host': 'docs.example.com',
        # 'docs_path': '/var/www/docs',
        # 'docs_user': 'www-data',
        # 'docs_password': 'my_seKret'

        # python versions for virtual environments.  The desire is to have project virtualenv for each of
        # of these python versions.
        'python_versions': ('27', '35', '26'),

        # python version (defined in 'python_versions') to build documentation with
        'doc_python_version': '27',

        # The virtualenv to use for documentation.  Note that the virtual environment
        # name should end in a two digit python version that is in python_versions.
        # Default is the virtualenv selected by doc_python_version
        'docs_venv': 'sphinx27',

        # python versions (defined in 'python_versions') to unit test with.  Defaults to 'wheel_python_versions'.
        'test_python_versions': ('26', '27', '35'),

        # python version (defined in 'python_versions') to build source distribution with
        'sdist_python_version': '27',

        # python version (defined in 'python_versions') to build source distribution with
        'metrics_python_versions': '27',

        # python versions (defined in 'python_versions') to build wheels for
        'wheel_python_versions': ('27', '35', '26'),

        # python version (defined in 'python_versions') to deploy to pypi server.
        # Defaults to first 'python_versions'.
        'deploy_python_version': '27',

        # For a full list of available configuration items, run: herring project::describe

        # when building, need to use the current virtual environments herring:
        'herring': 'herring/herring_main.py',

        # The project's logo image.  The default is generated from the project's "name".
        'logo_image': 'herring_logo.gif',

        # A URL to bugzilla.Defaults to the value of the BUGZILLA_URL environment variable or
        # "http://localhost".
        'bugzilla_url': 'https://bugzilla.example.com',

        # The following modules do not define any classes, so exclude them from generating
        # inheritance diagrams.
        'exclude_from_inheritance_diagrams': [
            'herring',
            'herring.herring_main',
            'herring.parallelize',
            'herring.support',
            'herring.support.list_helper',
            'herring.support.mkdir_p',
            'herring.support.safe_edit',
            'herring.support.terminalsize',
            'herring.support.toposort2',
            'herring.support.touch',
            'herring.support.utils',
        ],

        # usage_autoprogram
        # Use the sphinx autoprogram extension to document the command line application.
        # 'usage_autoprogram': 'True'
        'usage_autoprogram': False,
    }
)

Project.required_files()

if HerringFile.uninstalled_packages:
    print("You have missing packages.  You may install using the following command:")
    print("\n  pip install %s" % ' '.join(HerringFile.uninstalled_packages))

# debug("Python version: {version}".format(version=version))
# debug("Python path: {path}".format(path=pformat(path)))


@task(depends=['build', 'doc', 'test'])
def default():
    """ The default task(s) to run when none are specified """
    pass


@task()
def show():
    """ show all files in the project """
    for root_dir, dirs, files in os.walk('.'):
        # ignore hidden files and directories (starts with '.')
        files = [f for f in files if not f[0] == '.']
        dirs[:] = [d for d in dirs if not d[0] == '.']

        # ignore compiled python files
        files = [f for f in files if not f.endswith('.pyc')]
        dirs[:] = [d for d in dirs if not d == '__pycache__']

        info("%s (%d files)" % (root_dir, len(files)))
        for name in files:
            info("    %s" % name)


@task(namespace='demo', help='You may show arguments using:  -a value  or:  --arg value')
def args_demo():
    """ echos that task's arguments """
    info("argv: %s" % repr(task.argv))
    info("kwargs: %s" % repr(task.kwargs))


@task(namespace='demo', private=True)
def the():
    """test dependency"""
    print('The')


@task(namespace='demo', depends=['demo::the'], private=True)
def bang():
    """test error handling"""
    print('bang!')


@task(namespace='demo', private=True)
def big():
    """test running namespace tasks"""
    print('big')
    task_execute('demo::bang')


@task(namespace='demo', depends=['demo::the'], private=False)
def bigger():
    """test running namespace tasks"""
    print('bigger')
    sleep(10)
    task_execute(['demo::bang'])


@task(namespace='demo', private=True)
def boom():
    """test calling method"""
    bigger()
    print('Boom!')


@task(dependent_of='dummy')
def pre_dummy():
    """pre dummy hook"""
    print("Before doing nothing...")
