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

import os
from buildstream.testing import cli  # pylint: disable=unused-import
from buildstream.testing import create_repo
from buildstream import _yaml


def prepare_junction_project(cli, tmpdir):
    main_project = tmpdir.join("main")
    sub_project = tmpdir.join("sub")
    os.makedirs(str(main_project))
    os.makedirs(str(sub_project))

    _yaml.roundtrip_dump({"name": "main", "min-version": "2.0"}, str(main_project.join("project.conf")))
    _yaml.roundtrip_dump({"name": "sub", "min-version": "2.0"}, str(sub_project.join("project.conf")))

    import_dir = tmpdir.join("import")
    os.makedirs(str(import_dir))
    with open(str(import_dir.join("hello.txt")), "w") as f:
        f.write("hello!")

    import_repo_dir = tmpdir.join("import_repo")
    os.makedirs(str(import_repo_dir))
    import_repo = create_repo("git", str(import_repo_dir))
    import_ref = import_repo.create(str(import_dir))

    _yaml.roundtrip_dump(
        {"kind": "import", "sources": [import_repo.source_config(ref=import_ref)]}, str(sub_project.join("data.bst"))
    )

    sub_repo_dir = tmpdir.join("sub_repo")
    os.makedirs(str(sub_repo_dir))
    sub_repo = create_repo("git", str(sub_repo_dir))
    sub_ref = sub_repo.create(str(sub_project))

    _yaml.roundtrip_dump(
        {"kind": "junction", "sources": [sub_repo.source_config(ref=sub_ref)]}, str(main_project.join("sub.bst"))
    )

    args = ["source", "fetch", "sub.bst"]
    result = cli.run(project=str(main_project), args=args)
    result.assert_success()

    return str(main_project)


def open_cross_junction(cli, tmpdir):
    project = prepare_junction_project(cli, tmpdir)
    element = "sub.bst:data.bst"

    oldkey = cli.get_element_key(project, element)

    workspace = tmpdir.join("workspace")
    args = ["workspace", "open", "--directory", str(workspace), element]
    result = cli.run(project=project, args=args)
    result.assert_success()

    assert cli.get_element_state(project, element) == "buildable"
    assert os.path.exists(str(workspace.join("hello.txt")))
    assert cli.get_element_key(project, element) != oldkey

    return project, workspace


def test_open_cross_junction(cli, tmpdir):
    open_cross_junction(cli, tmpdir)


def test_list_cross_junction(cli, tmpdir):
    project, _ = open_cross_junction(cli, tmpdir)

    element = "sub.bst:data.bst"

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

    loaded = _yaml.load_data(result.output)
    workspaces = loaded.get_sequence("workspaces")
    assert len(workspaces) == 1
    first_workspace = workspaces.mapping_at(0)

    assert "element" in first_workspace
    assert first_workspace.get_str("element") == element


def test_close_cross_junction(cli, tmpdir):
    project, workspace = open_cross_junction(cli, tmpdir)

    element = "sub.bst:data.bst"
    args = ["workspace", "close", "--remove-dir", element]
    result = cli.run(project=project, args=args)
    result.assert_success()

    assert not os.path.exists(str(workspace))

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

    loaded = _yaml.load_data(result.output)
    workspaces = loaded.get_sequence("workspaces")
    assert not workspaces


def test_close_all_cross_junction(cli, tmpdir):
    project, workspace = open_cross_junction(cli, tmpdir)

    args = ["workspace", "close", "--remove-dir", "--all"]
    result = cli.run(project=project, args=args)
    result.assert_success()

    assert not os.path.exists(str(workspace))

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

    loaded = _yaml.load_data(result.output)
    workspaces = loaded.get_sequence("workspaces")
    assert not workspaces


def test_subdir_command_cross_junction(cli, tmpdir):
    # i.e. commands can be run successfully from a subdirectory of the
    # junction's workspace, in case project loading logic has gone wrong
    project = prepare_junction_project(cli, tmpdir)
    workspace = os.path.join(str(tmpdir), "workspace")
    junction_element = "sub.bst"

    # Open the junction as a workspace
    args = ["workspace", "open", "--directory", workspace, junction_element]
    result = cli.run(project=project, args=args)
    result.assert_success()

    # Run commands from a subdirectory of the workspace
    newdir = os.path.join(str(workspace), "newdir")
    element_name = "data.bst"
    os.makedirs(newdir)
    result = cli.run(project=str(workspace), args=["-C", newdir, "show", element_name])
    result.assert_success()
