"""
radish
~~~~~~

Behavior Driven Development tool for Python - the root from red to green

Copyright: MIT, Timo Furrer <tuxtimo@gmail.com>
"""

import pytest

from radish.extensionregistry import extension


def test_register_simple_extension_class(extensionregistry):
    """
    Test registering simple Extension class
    """

    # given
    class SimpleExtension:
        pass

    # when
    extensionregistry.register(SimpleExtension)

    # then
    assert len(extensionregistry.extensions) == 1
    assert extensionregistry.extensions[0] == SimpleExtension
    assert len(extensionregistry.loaded_extensions) == 0


def test_register_simple_extension_class_using_decorator(extensionregistry):
    """
    Test registering simple Extension class using the extension decorator
    """

    # given & when
    @extension
    class SimpleExtension:
        pass

    # then
    assert len(extensionregistry.extensions) == 1
    assert extensionregistry.extensions[0] == SimpleExtension
    assert len(extensionregistry.loaded_extensions) == 0


def test_loading_simple_extension(extensionregistry, mocker):
    """
    Test loading simple extension
    """

    # given
    @extension
    class SimpleExtension:
        LOAD_IF = staticmethod(lambda config: True)

    # when
    extensionregistry.load(mocker.MagicMock())

    # then
    assert len(extensionregistry.extensions) == 1
    assert extensionregistry.extensions[0] == SimpleExtension
    assert len(extensionregistry.loaded_extensions) == 1
    assert isinstance(extensionregistry.loaded_extensions[0], SimpleExtension)


# FIXME(TF): wrong behavior?!
def test_loading_invalid_extension(extensionregistry, mocker):
    """
    Test loading an invalid extension
    """

    # given
    @extension
    class SimpleExtension:
        pass

    # when
    extensionregistry.load(mocker.MagicMock())

    # then
    assert len(extensionregistry.extensions) == 1
    assert len(extensionregistry.loaded_extensions) == 0


def test_loading_extension_which_raises_exceptions_init(extensionregistry, mocker):
    """
    Test loading extension which raises exceptions in init
    """

    # given
    @extension
    class SimpleExtension:
        LOAD_IF = staticmethod(lambda config: True)

        def __init__(self):
            raise AssertionError("some error")

    # when
    with pytest.raises(AssertionError) as exc:
        extensionregistry.load(mocker.MagicMock())

    # then
    assert str(exc.value) == "some error"


def test_loading_simple_extension_if_wanted(extensionregistry, mocker):
    """
    Test loading extension if wanted by config
    """

    # given
    @extension
    class WantedExtension:
        LOAD_IF = staticmethod(lambda config: True)

    @extension
    class UnwantedExtension:
        LOAD_IF = staticmethod(lambda config: False)

    # when
    extensionregistry.load(mocker.MagicMock())

    # then
    assert len(extensionregistry.extensions) == 2
    assert len(extensionregistry.loaded_extensions) == 1
    assert isinstance(extensionregistry.loaded_extensions[0], WantedExtension)


def test_extension_loading_order(extensionregistry, mocker):
    """
    Test the loading order of extensions
    """

    # given
    @extension
    class SecondExtension:
        LOAD_IF = staticmethod(lambda config: True)
        # default prio = 1000

    @extension
    class FirstExtension:
        LOAD_IF = staticmethod(lambda config: True)
        LOAD_PRIORITY = 1

    @extension
    class ThirdExtension:
        LOAD_IF = staticmethod(lambda config: True)
        LOAD_PRIORITY = 10000

    # when
    extensionregistry.load(mocker.MagicMock())

    # then
    assert len(extensionregistry.loaded_extensions) == 3
    assert isinstance(extensionregistry.loaded_extensions[0], FirstExtension)
    assert isinstance(extensionregistry.loaded_extensions[1], SecondExtension)
    assert isinstance(extensionregistry.loaded_extensions[2], ThirdExtension)


def test_getting_extension_options(extensionregistry, mocker):
    """
    Test getting command line options from extensions
    """

    # given
    @extension
    class FooExtension:
        OPTIONS = [("--foo", "enable foo power")]

    @extension
    class BarExtension:
        OPTIONS = [
            ("--bar", "enable bar power"),
            ("--bar-pow", "enable magnitude of bar power"),
        ]

    @extension
    class BlaExtension:
        pass

    # when
    options = extensionregistry.get_options()
    option_description = extensionregistry.get_option_description()

    # then
    assert (
        options
        == """[--foo]
           [--bar]
           [--bar-pow]"""
    )

    assert (
        option_description
        == """--foo                                       enable foo power
    --bar                                       enable bar power
    --bar-pow                                   enable magnitude of bar power"""
    )
