# -*- coding: utf-8 -*-
from z3c.dependencychecker.modules import PythonDocstrings
from z3c.dependencychecker.tests.utils import write_source_file_at


NO_DOC = '\n'.join([
    'class MyClass(object):',
    '    pass',
])
INVALID_PYTHON = '\n'.join([
    '"""',
    '>>> and some text here that breaks the parser'
    '"""',
])
DOC_IN_MODULE = '\n'.join([
    '"""',
    'Random docstring with code to be evaluated.',
    '',
    '>>> import zope.component',
    '"""',
])
DOC_IN_FUNCTION = '\n'.join([
    'def test():'
    '    """Random docstring with code to be evaluated.',
    '',
    '    >>> import zope.component.adapter',
    '    """',
])
DOC_IN_CLASS = '\n'.join([
    'class MyClass(object):'
    '    """Random docstring with code to be evaluated.'
    '',
    '    >>> from zope.component import utility',
    '    """',
])
DOC_IN_METHOD = '\n'.join([
    'class MyClass(object):',
    '    def test(self):',
    '        """Docstring with code to be evaluated.',
    '',
    '        >>> import zope.interface',
    '        """',
])
MULTIPLE_IMPORTS_SAME_LINE = '\n'.join([
    'class MyClass(object):',
    '    def test(self):',
    '        """Docstring with code to be evaluated.',
    '',
    '        >>> from zope.interface import Interface, Attribute',
    '        """',
])
MULTIPLE_IMPORTS_DIFFERENT_LINES = '\n'.join([
    'class MyClass(object):',
    '    def test(self):',
    '        """Docstring with code to be evaluated.',
    '',
    '        >>> from zope.component import adapter',
    '        >>> from zope.component import utility',
    '        """',
])
MULTIPLE_IMPORTS_DIFFERENT_LINES_WITH_INVALID_CODE_LINES_BETWEEN = '\n'.join([
    'class MyClass(object):',
    '    def test(self):',
    '        """Docstring with code to be evaluated.',
    '',
    '        >>> from zope.component import adapter',
    '        >>> this should  be skipped and next line processed happily',
    '        >>> from zope.component import utility',
    '        """',
])


def _get_dependencies_on_file(folder, source):
    temporal_file = write_source_file_at(
        (folder.strpath, ),
        source_code=source,
    )

    docstring = PythonDocstrings(folder.strpath, temporal_file)
    dotted_names = [x.name for x in docstring.scan()]
    return dotted_names


def test_no_docstring(tmpdir):
    dotted_names = _get_dependencies_on_file(tmpdir, NO_DOC)
    assert len(dotted_names) == 0


def test_invalid_code_ignored(tmpdir):
    dotted_names = _get_dependencies_on_file(tmpdir, INVALID_PYTHON)
    assert len(dotted_names) == 0


def test_docstring_in_module(tmpdir):
    dotted_names = _get_dependencies_on_file(tmpdir, DOC_IN_MODULE)
    assert len(dotted_names) == 1


def test_docstring_in_module_details(tmpdir):
    dotted_names = _get_dependencies_on_file(tmpdir, DOC_IN_MODULE)
    assert dotted_names == ['zope.component', ]


def test_docstring_in_function(tmpdir):
    dotted_names = _get_dependencies_on_file(tmpdir, DOC_IN_FUNCTION)
    assert len(dotted_names) == 1


def test_docstring_in_function_details(tmpdir):
    dotted_names = _get_dependencies_on_file(tmpdir, DOC_IN_FUNCTION)
    assert dotted_names == ['zope.component.adapter', ]


def test_docstring_in_class(tmpdir):
    dotted_names = _get_dependencies_on_file(tmpdir, DOC_IN_CLASS)
    assert len(dotted_names) == 1


def test_docstring_in_class_details(tmpdir):
    dotted_names = _get_dependencies_on_file(tmpdir, DOC_IN_CLASS)
    assert dotted_names == ['zope.component.utility', ]


def test_docstring_in_method(tmpdir):
    dotted_names = _get_dependencies_on_file(tmpdir, DOC_IN_METHOD)
    assert len(dotted_names) == 1


def test_docstring_in_method_details(tmpdir):
    dotted_names = _get_dependencies_on_file(tmpdir, DOC_IN_METHOD)
    assert dotted_names == ['zope.interface', ]


def test_docstring_multiple_imports_same_line(tmpdir):
    dotted_names = _get_dependencies_on_file(
        tmpdir,
        MULTIPLE_IMPORTS_SAME_LINE,
    )
    assert len(dotted_names) == 2


def test_docstring_multiple_imports_same_line_details(tmpdir):
    dotted_names = _get_dependencies_on_file(
        tmpdir,
        MULTIPLE_IMPORTS_SAME_LINE,
    )
    assert 'zope.interface.Interface' in dotted_names
    assert 'zope.interface.Attribute' in dotted_names


def test_docstring_multiple_imports_different_line(tmpdir):
    dotted_names = _get_dependencies_on_file(
        tmpdir,
        MULTIPLE_IMPORTS_DIFFERENT_LINES,
    )
    assert len(dotted_names) == 2


def test_docstring_multiple_imports_same_different_line_details(tmpdir):
    dotted_names = _get_dependencies_on_file(
        tmpdir,
        MULTIPLE_IMPORTS_DIFFERENT_LINES,
    )
    assert 'zope.component.adapter' in dotted_names
    assert 'zope.component.utility' in dotted_names


def test_docstring_multiple_imports_with_invalid_lines(tmpdir):
    dotted_names = _get_dependencies_on_file(
        tmpdir,
        MULTIPLE_IMPORTS_DIFFERENT_LINES_WITH_INVALID_CODE_LINES_BETWEEN,
    )
    assert len(dotted_names) == 2


def test_docstring_multiple_imports_with_invalid_lines_details(tmpdir):
    dotted_names = _get_dependencies_on_file(
        tmpdir,
        MULTIPLE_IMPORTS_DIFFERENT_LINES_WITH_INVALID_CODE_LINES_BETWEEN,
    )
    assert 'zope.component.adapter' in dotted_names
    assert 'zope.component.utility' in dotted_names
