import os
import pytest

from buildstream._exceptions import LoadError, LoadErrorReason
from buildstream._loader import Loader, MetaElement
from tests.testutils import cli
from . import make_loader

DATA_DIR = os.path.join(
    os.path.dirname(os.path.realpath(__file__)),
    'dependencies',
)


##############################################################
#  Basics: Test behavior loading projects with dependencies  #
##############################################################
@pytest.mark.datafiles(DATA_DIR)
def test_two_files(datafiles):

    basedir = os.path.join(datafiles.dirname, datafiles.basename)
    loader = make_loader(basedir)
    element = loader.load(['elements/target.bst'])[0]

    assert(isinstance(element, MetaElement))
    assert(element.kind == 'pony')

    assert(len(element.dependencies) == 1)
    firstdep = element.dependencies[0]
    assert(isinstance(firstdep, MetaElement))
    assert(firstdep.kind == 'manual')


@pytest.mark.datafiles(DATA_DIR)
def test_shared_dependency(datafiles):

    basedir = os.path.join(datafiles.dirname, datafiles.basename)
    loader = make_loader(basedir)
    element = loader.load(['elements/shareddeptarget.bst'])[0]

    # Toplevel is 'pony' with 2 dependencies
    #
    assert(isinstance(element, MetaElement))
    assert(element.kind == 'pony')
    assert(len(element.dependencies) == 2)

    # The first specified dependency is 'thefirstdep'
    #
    firstdep = element.dependencies[0]
    assert(isinstance(firstdep, MetaElement))
    assert(firstdep.kind == 'manual')
    assert(len(firstdep.dependencies) == 0)

    # The second specified dependency is 'shareddep'
    #
    shareddep = element.dependencies[1]
    assert(isinstance(shareddep, MetaElement))
    assert(shareddep.kind == 'shareddep')
    assert(len(shareddep.dependencies) == 1)

    # The element which shareddep depends on is
    # the same element in memory as firstdep
    #
    shareddepdep = shareddep.dependencies[0]
    assert(isinstance(shareddepdep, MetaElement))

    # Assert they are in fact the same LoadElement
    #
    # Note we must use 'is' to test that both variables
    # refer to the same object in memory, not a regular
    # equality test with '==' which is one of those operator
    # overridable thingies.
    #
    assert(shareddepdep is firstdep)


@pytest.mark.datafiles(DATA_DIR)
def test_dependency_dict(datafiles):

    basedir = os.path.join(datafiles.dirname, datafiles.basename)
    loader = make_loader(basedir)
    element = loader.load(['elements/target-depdict.bst'])[0]

    assert(isinstance(element, MetaElement))
    assert(element.kind == 'pony')

    assert(len(element.dependencies) == 1)
    firstdep = element.dependencies[0]
    assert(isinstance(firstdep, MetaElement))
    assert(firstdep.kind == 'manual')


@pytest.mark.datafiles(DATA_DIR)
def test_invalid_dependency_declaration(datafiles):
    basedir = os.path.join(datafiles.dirname, datafiles.basename)
    loader = make_loader(basedir)

    with pytest.raises(LoadError) as exc:
        element = loader.load(['elements/invaliddep.bst'])[0]

    assert (exc.value.reason == LoadErrorReason.INVALID_DATA)


@pytest.mark.datafiles(DATA_DIR)
def test_circular_dependency(datafiles):
    basedir = os.path.join(datafiles.dirname, datafiles.basename)
    loader = make_loader(basedir)

    with pytest.raises(LoadError) as exc:
        element = loader.load(['elements/circulartarget.bst'])[0]

    assert (exc.value.reason == LoadErrorReason.CIRCULAR_DEPENDENCY)
    assert ("seconddep" in exc.value.args[0])


@pytest.mark.datafiles(DATA_DIR)
def test_invalid_dependency_type(datafiles):
    basedir = os.path.join(datafiles.dirname, datafiles.basename)
    loader = make_loader(basedir)

    with pytest.raises(LoadError) as exc:
        element = loader.load(['elements/invaliddeptype.bst'])[0]

    assert (exc.value.reason == LoadErrorReason.INVALID_DATA)


@pytest.mark.datafiles(DATA_DIR)
def test_build_dependency(datafiles):
    basedir = os.path.join(datafiles.dirname, datafiles.basename)
    loader = make_loader(basedir)
    element = loader.load(['elements/builddep.bst'])[0]

    assert(isinstance(element, MetaElement))
    assert(element.kind == 'pony')

    assert(len(element.build_dependencies) == 1)
    firstdep = element.build_dependencies[0]
    assert(isinstance(firstdep, MetaElement))

    assert(len(element.dependencies) == 0)


@pytest.mark.datafiles(DATA_DIR)
def test_runtime_dependency(datafiles):
    basedir = os.path.join(datafiles.dirname, datafiles.basename)
    loader = make_loader(basedir)
    element = loader.load(['elements/runtimedep.bst'])[0]

    assert(isinstance(element, MetaElement))
    assert(element.kind == 'pony')

    assert(len(element.dependencies) == 1)
    firstdep = element.dependencies[0]
    assert(isinstance(firstdep, MetaElement))

    assert(len(element.build_dependencies) == 0)


@pytest.mark.datafiles(DATA_DIR)
def test_build_runtime_dependency(datafiles):
    basedir = os.path.join(datafiles.dirname, datafiles.basename)
    loader = make_loader(basedir)
    element = loader.load(['elements/target.bst'])[0]

    assert(isinstance(element, MetaElement))
    assert(element.kind == 'pony')

    assert(len(element.dependencies) == 1)
    assert(len(element.build_dependencies) == 1)
    firstdep = element.dependencies[0]
    assert(isinstance(firstdep, MetaElement))
    firstbuilddep = element.build_dependencies[0]
    assert(firstdep == firstbuilddep)


@pytest.mark.datafiles(DATA_DIR)
def test_all_dependency(datafiles):
    basedir = os.path.join(datafiles.dirname, datafiles.basename)
    loader = make_loader(basedir)
    element = loader.load(['elements/alldep.bst'])[0]

    assert(isinstance(element, MetaElement))
    assert(element.kind == 'pony')

    assert(len(element.dependencies) == 1)
    assert(len(element.build_dependencies) == 1)
    firstdep = element.dependencies[0]
    assert(isinstance(firstdep, MetaElement))
    firstbuilddep = element.build_dependencies[0]
    assert(firstdep == firstbuilddep)


@pytest.mark.datafiles(DATA_DIR)
def test_list_build_dependency(cli, datafiles):
    project = str(datafiles)

    # Check that the pipeline includes the build dependency
    deps = cli.get_pipeline(project, ['elements/builddep-list.bst'], scope="build")
    assert "elements/firstdep.bst" in deps


@pytest.mark.datafiles(DATA_DIR)
def test_list_runtime_dependency(cli, datafiles):
    project = str(datafiles)

    # Check that the pipeline includes the runtime dependency
    deps = cli.get_pipeline(project, ['elements/runtimedep-list.bst'], scope="run")
    assert "elements/firstdep.bst" in deps


@pytest.mark.datafiles(DATA_DIR)
def test_list_dependencies_combined(cli, datafiles):
    project = str(datafiles)

    # Check that runtime deps get combined
    rundeps = cli.get_pipeline(project, ['elements/list-combine.bst'], scope="run")
    assert "elements/firstdep.bst" not in rundeps
    assert "elements/seconddep.bst" in rundeps
    assert "elements/thirddep.bst" in rundeps

    # Check that build deps get combined
    builddeps = cli.get_pipeline(project, ['elements/list-combine.bst'], scope="build")
    assert "elements/firstdep.bst" in builddeps
    assert "elements/seconddep.bst" not in builddeps
    assert "elements/thirddep.bst" in builddeps


@pytest.mark.datafiles(DATA_DIR)
def test_list_overlap(cli, datafiles):
    project = str(datafiles)

    # Check that dependencies get merged
    rundeps = cli.get_pipeline(project, ['elements/list-overlap.bst'], scope="run")
    assert "elements/firstdep.bst" in rundeps
    builddeps = cli.get_pipeline(project, ['elements/list-overlap.bst'], scope="build")
    assert "elements/firstdep.bst" in builddeps
