import os

import pytest
import imp


def pytest_addoption(parser):
    default = 'scenario.py'
    parser.addoption(
        "--scenario",
        action="store",
        default=default,
        help="YAML file defining scenarios to test. Currently defaults to: %s" % default
    )


def load_scenario_config(filepath, **kw):
    '''
    Creates a configuration dictionary from a file.

    :param filepath: The path to the file.
    '''

    abspath = os.path.abspath(os.path.expanduser(filepath))
    conf_dict = {}
    if not os.path.isfile(abspath):
        raise RuntimeError('`%s` is not a file.' % abspath)

    # First, make sure the code will actually compile (and has no SyntaxErrors)
    with open(abspath, 'rb') as f:
        compiled = compile(f.read(), abspath, 'exec')

    # Next, attempt to actually import the file as a module.
    # This provides more verbose import-related error reporting than exec()
    absname, _ = os.path.splitext(abspath)
    basepath, module_name = absname.rsplit(os.sep, 1)
    imp.load_module(
        module_name,
        *imp.find_module(module_name, [basepath])
    )

    # If we were able to import as a module, actually exec the compiled code
    exec(compiled, globals(), conf_dict)
    conf_dict['__file__'] = abspath
    return conf_dict


def pytest_configure_node(node):
    node_id = node.slaveinput['slaveid']
    scenario_path = os.path.abspath(node.config.getoption('--scenario'))
    scenario = load_scenario_config(scenario_path)
    node.slaveinput['node_config'] = scenario['nodes'][node_id]
    node.slaveinput['scenario_config'] = scenario


@pytest.fixture(scope='session')
def node_config(request):
    return request.config.slaveinput['node_config']


@pytest.fixture(scope="session")
def scenario_config(request):
    return request.config.slaveinput['scenario_config']


def pytest_report_header(config):
    """
    Hook to add extra information about the execution environment and to be
    able to debug what did the magical args got expanded to
    """
    lines = []
    scenario_path = str(config.rootdir.join(config.getoption('--scenario')))
    if not config.remote_execution:
        lines.append('execution environment: local')
    else:
        lines.append('execution environment: remote')
        lines.append('loaded scenario: %s' % scenario_path)
    lines.append('expanded args: %s' % config.extended_args)
    return lines


def pytest_cmdline_preparse(args, config):
    # Note: we can only do our magical args expansion if we aren't already in
    # a remote node via xdist/execnet so return quickly if we can't do magic.
    # TODO: allow setting an environment variable that helps to skip this kind
    # of magical argument expansion
    if os.getcwd().endswith('pyexecnetcache'):
        return

    scenario_path = os.path.abspath(config.getoption('--scenario'))

    scenarios = load_scenario_config(scenario_path, args=args)
    rsync_dir = os.path.dirname(str(config.rootdir.join('functional')))
    test_path = str(config.rootdir.join('functional/tests'))
    nodes = []
    config.remote_execution = True
    for node in scenarios.get('nodes', []):
        nodes.append('--tx')
        nodes.append('vagrant_ssh={node_name}//id={node_name}'.format(node_name=node))
    args[:] = args + ['--max-slave-restart', '0', '--dist=each'] + nodes + ['--rsyncdir', rsync_dir, test_path]
    config.extended_args = ' '.join(args)

import pytest


@pytest.fixture()
def CephNode(Ansible, request):
    vars = Ansible.get_variables()
    node_type = vars["group_names"][0]
    if not request.node.get_marker(node_type):
        pytest.skip("Not a valid test for node type")


def pytest_collection_modifyitems(session, config, items):
    for item in items:
        test_path = item.location[0]
        if "mon" in test_path:
            item.add_marker(pytest.mark.mons)
        elif "osd" in test_path:
            item.add_marker(pytest.mark.osds)
        elif "mds" in test_path:
            item.add_marker(pytest.mark.mdss)
        elif "rgw" in test_path:
            item.add_marker(pytest.mark.rgws)
        else:
            item.add_marker(pytest.mark.all)

change conftest.py to support dynamic markers and test selection