# coding=utf-8
"""
Tasks for running various tests for Rookeries

:copyright: Copyright 2013-2016, Dorian Pula <dorian.pula@amber-penguin-software.ca>
:license: AGPL v3+
"""

import invoke as inv
from invoke import exceptions as inv_err

from . import db, utils


@inv.task
def clean(ctx):
    """
    Cleans test reports and artifacts.

    :param ctx: Context of the invoke task.
    """
    test_folders = ['cover']
    utils.delete_in_path_list(test_folders)


@inv.task
def style(ctx):
    """
    Test the coding style using Flake8.

    :param ctx: Context of the invoke task.
    """
    inv.run('flake8 --exclude=docs --max-line-length=120 --max-complexity=10', echo=True, pty=True)


def _prepare_py_test_command(test_path, check_coverage_on='', verbosity=0, **extra_test_params):
    verbose_flag = ''
    if verbosity > 0:
        verbose_flag = '-{}'.format('v' * verbosity)

    if verbosity >= 3:
        verbose_flag = f'{verbose_flag} -r a'

    coverage_flag = ''
    if check_coverage_on:
        coverage_flag = f'--cov {check_coverage_on} --cov-report=term-missing --capture=no'
    additional_test_params = ' '.join(
        ['--{}={}'.format(key.replace('_', '-'), value) for (key, value) in extra_test_params.items()])
    return f'py.test {test_path} {coverage_flag} {verbose_flag} {additional_test_params}'


@inv.task
def server(ctx, db_connection=db.DEFAULT_DB_CONNECTION, keep_test_db=False, verbosity=0):
    """
    Test the server webapp using both unit and integration tests.

    :param ctx: Context of the invoke task.
    :param db_connection: Connection to the CouchDB database to go against.
    :param keep_test_db: Keep the test data and database around.
    :param verbosity: The amount of logging from the test.  Default is 0 and is the lowest.  3 is the highest.
    """

    try:
        with db.test_database(db_connection=db_connection, keep_test_db=keep_test_db):
            test_command = _prepare_py_test_command('tests/server', check_coverage_on='rookeries', verbosity=verbosity)
            inv.run(test_command, echo=True, pty=True)

    except inv_err.Failure as err:
        print('Server test failed." \n')
        raise err


@inv.task
def functional(ctx, server_host='localhost', port=5000, db_connection=db.DEFAULT_DB_CONNECTION,
               keep_test_db=False, verbosity=0, test_tag=''):
    """
    Test the high-level functionality of rookeries.

    :param ctx: Context of the invoke task.
    :param server_host: The hostname of the server to test.
    :param port: The port that the server runs on.
    :param db_connection: Connection to the CouchDB database to go against.
    :param keep_test_db: Keep the test data and database around.
    :param verbosity: The amount of logging from the test.  Default is 0 and is the lowest.  3 is the highest.
    :param test_tag: Optional tag (pytest mark) to run individually decorated tests in suite.
    """
    try:
        with db.test_database(db_connection=db_connection, keep_test_db=keep_test_db):
            test_command = _prepare_py_test_command(
                'tests/functional', verbosity=verbosity, server_hostname=server_host, server_port=port,
            )
            if test_tag:
                test_command = f'{test_command} -m {test_tag}'
            inv.run(test_command, echo=True, pty=True)

    except inv_err.Failure as err:
        print('Server test failed." \n')
        raise err


@inv.task(clean, server, style, name='all')
def test_all(ctx):
    print(u'Everything looks good! ☻')
