# 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_integration as cli  # pylint: disable=unused-import
from buildstream.testing._utils.site import HAVE_SANDBOX, CASD_SEPARATE_USER


DATA_DIR = os.path.join(os.path.dirname(os.path.realpath(__file__)), "project")


def create_test_file(*path, mode=0o644, content="content\n"):
    path = os.path.join(*path)
    os.makedirs(os.path.dirname(path), exist_ok=True)
    with open(path, "w") as f:
        f.write(content)
        os.fchmod(f.fileno(), mode)


def create_test_directory(*path, mode=0o644):
    create_test_file(*path, ".keep", content="")
    path = os.path.join(*path)
    os.chmod(path, mode)


@pytest.mark.integration
@pytest.mark.datafiles(DATA_DIR)
@pytest.mark.skipif(not HAVE_SANDBOX, reason="Only available with a functioning sandbox")
def test_deterministic_source_local(cli, tmpdir, datafiles):
    """Only user rights should be considered for local source.
    """
    project = str(datafiles)
    element_name = "test.bst"
    element_path = os.path.join(project, "elements", element_name)
    sourcedir = os.path.join(project, "source")

    element = {
        "kind": "manual",
        "depends": [{"filename": "base.bst", "type": "build"}],
        "sources": [{"kind": "local", "path": "source"}],
        "config": {"install-commands": ['ls -l >"%{install-root}/ls-l"']},
    }
    _yaml.roundtrip_dump(element, element_path)

    def get_value_for_mask(mask):
        checkoutdir = os.path.join(str(tmpdir), "checkout-{}".format(mask))

        create_test_file(sourcedir, "a.txt", mode=0o644 & mask)
        create_test_file(sourcedir, "b.txt", mode=0o755 & mask)
        create_test_file(sourcedir, "c.txt", mode=0o4755 & mask)
        create_test_file(sourcedir, "d.txt", mode=0o2755 & mask)
        create_test_file(sourcedir, "e.txt", mode=0o1755 & mask)
        create_test_directory(sourcedir, "dir-a", mode=0o0755 & mask)
        create_test_directory(sourcedir, "dir-b", mode=0o4755 & mask)
        create_test_directory(sourcedir, "dir-c", mode=0o2755 & mask)
        create_test_directory(sourcedir, "dir-d", mode=0o1755 & mask)
        try:
            test_values = []
            result = cli.run(project=project, args=["build", element_name])
            result.assert_success()

            result = cli.run(project=project, args=["artifact", "checkout", element_name, "--directory", checkoutdir])
            result.assert_success()

            with open(os.path.join(checkoutdir, "ls-l"), "r") as f:
                for line in f.readlines():
                    test_values.append(line.split()[0] + " " + line.split()[-1])
                return test_values
        finally:
            cli.remove_artifact_from_cache(project, element_name)

    if CASD_SEPARATE_USER:
        # buildbox-casd running as separate user of the same group can't
        # read files with too restrictive permissions.
        assert get_value_for_mask(0o7777) == get_value_for_mask(0o0770)
    else:
        assert get_value_for_mask(0o7777) == get_value_for_mask(0o0700)
