# Pylint doesn't play well with fixtures and dependency injection from pytest
# pylint: disable=redefined-outer-name

import os

import pytest

from buildstream import _yaml
from buildstream.testing import cli, create_repo  # pylint: disable=unused-import
from tests.testutils import create_artifact_share

# project directory
DATA_DIR = os.path.join(os.path.dirname(os.path.realpath(__file__)), "default-target",)


#
# When no target is default, then expect all targets to be built
#
@pytest.mark.datafiles(DATA_DIR)
def test_no_default(cli, datafiles):
    project = str(datafiles)
    all_targets = ["dummy_1.bst", "dummy_2.bst", "dummy_3.bst", "dummy_stack.bst"]

    result = cli.run(project=project, args=["build"])
    result.assert_success()

    states = cli.get_element_states(project, all_targets)
    assert all(states[e] == "cached" for e in all_targets)


#
# When the stack is specified as the default target, then
# expect only it and it's dependencies to be built
#
@pytest.mark.datafiles(DATA_DIR)
def test_default_target(cli, datafiles):
    project = str(datafiles)
    project_path = os.path.join(project, "project.conf")

    # First, modify project configuration to set a default target
    project_conf = {
        "name": "test-default-target",
        "min-version": "2.0",
        "element-path": "elements",
        "defaults": {"targets": ["dummy_stack.bst"]},
    }
    _yaml.roundtrip_dump(project_conf, project_path)

    # dummy_stack only depends on dummy_1 and dummy_2, but not dummy_3
    all_targets = ["dummy_1.bst", "dummy_2.bst", "dummy_stack.bst"]

    result = cli.run(project=project, args=["build"])
    result.assert_success()

    states = cli.get_element_states(project, all_targets)
    assert all(states[e] == "cached" for e in all_targets)

    # assert that dummy_3 isn't included in the output
    assert "dummy_3.bst" not in states


#
# Even when there is a junction, expect that the elements in the
# subproject referred to by the toplevel project are built when
# calling `bst build` and no default is specified.
#
@pytest.mark.datafiles(DATA_DIR)
def test_no_default_with_junction(cli, datafiles):
    project = str(datafiles)
    junction_path = os.path.join(project, "elements", "junction.bst")
    target_path = os.path.join(project, "elements", "junction-target.bst")

    # First, create a junction element to refer to the subproject
    junction_config = {"kind": "junction", "sources": [{"kind": "local", "path": "files/sub-project",}]}
    _yaml.roundtrip_dump(junction_config, junction_path)

    # Then, create a stack element with dependency on cross junction element
    target_config = {"kind": "stack", "depends": ["junction.bst:dummy_subproject.bst"]}
    _yaml.roundtrip_dump(target_config, target_path)

    # Now try to perform a build
    # This should automatically fetch the junction at load time.
    result = cli.run(project=project, args=["build"])
    result.assert_success()

    assert cli.get_element_state(project, "junction.bst:dummy_subproject.bst") == "cached"
    assert cli.get_element_state(project, "junction-target.bst") == "cached"


###################################
#     track/fetch operations      #
###################################


@pytest.mark.datafiles(DATA_DIR)
def test_default_target_track(cli, tmpdir, datafiles):
    project = str(datafiles)
    project_path = os.path.join(project, "project.conf")
    target = "track-fetch-test.bst"

    # First, create an element with trackable sources
    repo = create_repo("git", str(tmpdir))
    repo.create(project)
    element_conf = {"kind": "import", "sources": [repo.source_config()]}
    _yaml.roundtrip_dump(element_conf, os.path.join(project, "elements", target))

    # Then, make it the default target
    project_conf = {
        "name": "test-default-target",
        "min-version": "2.0",
        "element-path": "elements",
        "defaults": {"targets": [target]},
    }
    _yaml.roundtrip_dump(project_conf, project_path)

    # Setup finished. Track it now
    assert cli.get_element_state(project, target) == "no reference"
    result = cli.run(project=project, args=["source", "track"])
    result.assert_success()
    # Tracking will result in fetching it automatically, so we expect the state
    # to be buildable.
    assert cli.get_element_state(project, target) == "buildable"


@pytest.mark.datafiles(DATA_DIR)
def test_default_target_fetch(cli, tmpdir, datafiles):
    project = str(datafiles)
    project_path = os.path.join(project, "project.conf")
    target = "track-fetch-test.bst"

    # First, create an element with trackable sources
    repo = create_repo("git", str(tmpdir))
    ref = repo.create(project)
    element_conf = {"kind": "import", "sources": [repo.source_config(ref=ref)]}
    _yaml.roundtrip_dump(element_conf, os.path.join(project, "elements", target))

    # Then, make it the default target
    project_conf = {
        "name": "test-default-target",
        "min-version": "2.0",
        "element-path": "elements",
        "defaults": {"targets": [target]},
    }
    _yaml.roundtrip_dump(project_conf, project_path)

    # Setup finished. Track it now
    assert cli.get_element_state(project, target) == "fetch needed"
    result = cli.run(project=project, args=["source", "fetch"])
    result.assert_success()
    assert cli.get_element_state(project, target) == "buildable"


###################################
#      pull/push operations      #
###################################


@pytest.mark.datafiles(DATA_DIR)
def test_default_target_push_pull(cli, tmpdir, datafiles):
    project = str(datafiles)
    project_path = os.path.join(project, "project.conf")
    target = "dummy_1.bst"

    # Set a default target
    project_conf = {
        "name": "test-default-target",
        "min-version": "2.0",
        "element-path": "elements",
        "defaults": {"targets": [target]},
    }
    _yaml.roundtrip_dump(project_conf, project_path)

    # Build the target
    result = cli.run(project=project, args=["build"])
    result.assert_success()
    assert cli.get_element_state(project, target) == "cached"

    with create_artifact_share(os.path.join(str(tmpdir), "artifactshare")) as share:
        # Push the artifacts
        cli.configure({"artifacts": {"servers": [{"url": share.repo, "push": True}]}})
        result = cli.run(project=project, args=["artifact", "push"])
        result.assert_success()

        # Delete local artifacts
        # Note that `artifact delete` does not support default targets
        result = cli.run(project=project, args=["artifact", "delete", target])
        result.assert_success()

        # Target should be buildable now, and we should be able to pull it
        assert cli.get_element_state(project, target) == "buildable"
        result = cli.run(project=project, args=["artifact", "pull"])
        assert cli.get_element_state(project, target) == "cached"
