# 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


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')
@pytest.mark.xfail(HAVE_SANDBOX == 'buildbox', reason='Not working with BuildBox')
# Not stricked xfail as only fails in CI
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:
            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:
                return f.read()
        finally:
            cli.remove_artifact_from_cache(project, element_name)

    assert get_value_for_mask(0o7777) == get_value_for_mask(0o0700)
