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

import os
import re
import shutil
import itertools

import pytest

from buildstream import _yaml
from buildstream.testing import create_repo
from buildstream.testing import cli  # pylint: disable=unused-import
from buildstream._exceptions import ErrorDomain
from tests.testutils import generate_junction

from . import configure_project

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


def create_element(repo, name, path, dependencies, ref=None):
    element = {
        'kind': 'import',
        'sources': [
            repo.source_config(ref=ref)
        ],
        'depends': dependencies
    }
    _yaml.roundtrip_dump(element, os.path.join(path, name))


@pytest.mark.datafiles(os.path.join(DATA_DIR))
@pytest.mark.parametrize("strict", [True, False], ids=["strict", "no-strict"])
@pytest.mark.parametrize("ref_storage", [('inline'), ('project.refs')])
@pytest.mark.parametrize("track_targets,exceptions,tracked", [
    # Test with no exceptions
    (['0.bst'], [], ['0.bst', '2.bst', '3.bst', '4.bst', '5.bst', '6.bst', '7.bst']),
    (['3.bst'], [], ['3.bst', '4.bst', '5.bst', '6.bst']),
    (['2.bst', '3.bst'], [], ['2.bst', '3.bst', '4.bst', '5.bst', '6.bst', '7.bst']),

    # Test excepting '2.bst'
    (['0.bst'], ['2.bst'], ['0.bst', '3.bst', '4.bst', '5.bst', '6.bst']),
    (['3.bst'], ['2.bst'], []),
    (['2.bst', '3.bst'], ['2.bst'], ['3.bst', '4.bst', '5.bst', '6.bst']),

    # Test excepting '2.bst' and '3.bst'
    (['0.bst'], ['2.bst', '3.bst'], ['0.bst']),
    (['3.bst'], ['2.bst', '3.bst'], []),
    (['2.bst', '3.bst'], ['2.bst', '3.bst'], [])
])
def test_build_track(cli, datafiles, tmpdir, ref_storage, strict,
                     track_targets, exceptions, tracked):
    project = str(datafiles)
    dev_files_path = os.path.join(project, 'files', 'dev-files')
    element_path = os.path.join(project, 'elements')

    repo = create_repo('git', str(tmpdir))
    ref = repo.create(dev_files_path)

    configure_project(project, {
        'ref-storage': ref_storage
    })
    cli.configure({
        'projects': {
            'test': {
                'strict': strict
            }
        }
    })

    create_elements = {
        '0.bst': [
            '2.bst',
            '3.bst'
        ],
        '2.bst': [
            '3.bst',
            '7.bst'
        ],
        '3.bst': [
            '4.bst',
            '5.bst',
            '6.bst'
        ],
        '4.bst': [],
        '5.bst': [],
        '6.bst': [
            '5.bst'
        ],
        '7.bst': []
    }

    initial_project_refs = {}
    for element, dependencies in create_elements.items():
        # Test the element inconsistency resolution by ensuring that
        # only elements that aren't tracked have refs
        if element in set(tracked):
            # Elements which should not have a ref set
            #
            create_element(repo, element, element_path, dependencies)
        elif ref_storage == 'project.refs':
            # Store a ref in project.refs
            #
            create_element(repo, element, element_path, dependencies)
            initial_project_refs[element] = [{'ref': ref}]
        else:
            # Store a ref in the element itself
            #
            create_element(repo, element, element_path, dependencies, ref=ref)

    # Generate initial project.refs
    if ref_storage == 'project.refs':
        project_refs = {
            'projects': {
                'test': initial_project_refs
            }
        }
        _yaml.roundtrip_dump(project_refs, os.path.join(project, 'project.refs'))

    args = ['build']
    args += itertools.chain.from_iterable(zip(itertools.repeat('--track'), track_targets))
    args += itertools.chain.from_iterable(zip(itertools.repeat('--track-except'), exceptions))
    args += ['0.bst']

    result = cli.run(project=project, silent=True, args=args)
    result.assert_success()

    # Assert that the main target 0.bst is cached
    assert cli.get_element_state(project, '0.bst') == 'cached'

    # Assert that we tracked exactly the elements we expected to
    tracked_elements = result.get_tracked_elements()
    assert set(tracked_elements) == set(tracked)

    # Delete element sources
    source_dir = os.path.join(project, 'cache', 'sources')
    shutil.rmtree(source_dir)
    source_protos = os.path.join(project, 'cache', 'source_protos')
    shutil.rmtree(source_protos)

    # Delete artifacts one by one and assert element states
    for target in set(tracked):
        cli.remove_artifact_from_cache(project, target)

        # Assert that it's tracked
        assert cli.get_element_state(project, target) == 'fetch needed'

    # Assert there was a project.refs created, depending on the configuration
    if ref_storage == 'project.refs':
        assert os.path.exists(os.path.join(project, 'project.refs'))
    else:
        assert not os.path.exists(os.path.join(project, 'project.refs'))


# This tests a very specific scenario:
#
#  o Local cache is empty
#  o Strict mode is disabled
#  o The build target has only build dependencies
#  o The build is launched with --track-all
#
# In this scenario, we have encountered bugs where BuildStream returns
# successfully after tracking completes without ever pulling, fetching or
# building anything.
#
@pytest.mark.datafiles(DATA_DIR)
@pytest.mark.parametrize("strict", [True, False], ids=["strict", "no-strict"])
@pytest.mark.parametrize("ref_storage", [('inline'), ('project.refs')])
def test_build_track_all(cli, tmpdir, datafiles, strict, ref_storage):
    project = os.path.join(datafiles.dirname, datafiles.basename)
    subproject_path = os.path.join(project, 'files', 'sub-project')
    subproject_element_path = os.path.join(project, 'files', 'sub-project', 'elements')
    junction_path = os.path.join(project, 'elements', 'junction.bst')
    element_path = os.path.join(project, 'elements')
    dev_files_path = os.path.join(project, 'files', 'dev-files')

    configure_project(project, {
        'ref-storage': ref_storage
    })
    cli.configure({
        'projects': {
            'test': {
                'strict': strict
            }
        }
    })

    # We need a repo for real trackable elements
    repo = create_repo('git', str(tmpdir))
    ref = repo.create(dev_files_path)

    # Create a trackable element to depend on the cross junction element,
    # this one has it's ref resolved already
    create_element(repo, 'sub-target.bst', subproject_element_path, ['import-etc.bst'], ref=ref)

    # Create a trackable element to depend on the cross junction element
    create_element(repo, 'target.bst', element_path, [
        {
            'junction': 'junction.bst',
            'filename': 'sub-target.bst'
        }
    ])

    # Create a repo to hold the subproject and generate a junction element for it
    generate_junction(tmpdir, subproject_path, junction_path, store_ref=False)

    # Now create a compose element at the top level
    element = {
        'kind': 'compose',
        'depends': [
            {
                'filename': 'target.bst',
                'type': 'build'
            }
        ]
    }
    _yaml.roundtrip_dump(element, os.path.join(element_path, 'composed.bst'))

    # Track the junction itself first.
    result = cli.run(project=project, args=['source', 'track', 'junction.bst'])
    result.assert_success()

    # Build it with --track-all
    result = cli.run(project=project, silent=True, args=['build', '--track-all', 'composed.bst'])
    result.assert_success()

    # Assert that the main target is cached as a result
    assert cli.get_element_state(project, 'composed.bst') == 'cached'


@pytest.mark.datafiles(os.path.join(DATA_DIR))
@pytest.mark.parametrize("track_targets,exceptions,tracked", [
    # Test with no exceptions
    (['0.bst'], [], ['0.bst', '2.bst', '3.bst', '4.bst', '5.bst', '6.bst', '7.bst']),
    (['3.bst'], [], ['3.bst', '4.bst', '5.bst', '6.bst']),
    (['2.bst', '3.bst'], [], ['2.bst', '3.bst', '4.bst', '5.bst', '6.bst', '7.bst']),

    # Test excepting '2.bst'
    (['0.bst'], ['2.bst'], ['0.bst', '3.bst', '4.bst', '5.bst', '6.bst']),
    (['3.bst'], ['2.bst'], []),
    (['2.bst', '3.bst'], ['2.bst'], ['3.bst', '4.bst', '5.bst', '6.bst']),

    # Test excepting '2.bst' and '3.bst'
    (['0.bst'], ['2.bst', '3.bst'], ['0.bst']),
    (['3.bst'], ['2.bst', '3.bst'], []),
    (['2.bst', '3.bst'], ['2.bst', '3.bst'], [])
])
def test_build_track_update(cli, datafiles, tmpdir, track_targets,
                            exceptions, tracked):
    project = str(datafiles)
    dev_files_path = os.path.join(project, 'files', 'dev-files')
    element_path = os.path.join(project, 'elements')

    repo = create_repo('git', str(tmpdir))
    ref = repo.create(dev_files_path)

    create_elements = {
        '0.bst': [
            '2.bst',
            '3.bst'
        ],
        '2.bst': [
            '3.bst',
            '7.bst'
        ],
        '3.bst': [
            '4.bst',
            '5.bst',
            '6.bst'
        ],
        '4.bst': [],
        '5.bst': [],
        '6.bst': [
            '5.bst'
        ],
        '7.bst': []
    }
    for element, dependencies in create_elements.items():
        # We set a ref for all elements, so that we ensure that we
        # only track exactly those elements that we want to track,
        # even if others can be tracked
        create_element(repo, element, element_path, dependencies, ref=ref)
        repo.add_commit()

    args = ['build']
    args += itertools.chain.from_iterable(zip(itertools.repeat('--track'), track_targets))
    args += itertools.chain.from_iterable(zip(itertools.repeat('--track-except'), exceptions))
    args += ['0.bst']

    result = cli.run(project=project, silent=True, args=args)
    tracked_elements = result.get_tracked_elements()

    assert set(tracked_elements) == set(tracked)


@pytest.mark.datafiles(os.path.join(DATA_DIR))
@pytest.mark.parametrize("track_targets,exceptions", [
    # Test tracking the main target element, but excepting some of its
    # children
    (['0.bst'], ['6.bst']),

    # Test only tracking a child element
    (['3.bst'], []),
])
def test_build_track_inconsistent(cli, datafiles, tmpdir,
                                  track_targets, exceptions):
    project = str(datafiles)
    dev_files_path = os.path.join(project, 'files', 'dev-files')
    element_path = os.path.join(project, 'elements')

    repo = create_repo('git', str(tmpdir))
    repo.create(dev_files_path)

    create_elements = {
        '0.bst': [
            '2.bst',
            '3.bst'
        ],
        '2.bst': [
            '3.bst',
            '7.bst'
        ],
        '3.bst': [
            '4.bst',
            '5.bst',
            '6.bst'
        ],
        '4.bst': [],
        '5.bst': [],
        '6.bst': [
            '5.bst'
        ],
        '7.bst': []
    }
    for element, dependencies in create_elements.items():
        # We don't add refs so that all elements *have* to be tracked
        create_element(repo, element, element_path, dependencies)

    args = ['build']
    args += itertools.chain.from_iterable(zip(itertools.repeat('--track'), track_targets))
    args += itertools.chain.from_iterable(zip(itertools.repeat('--track-except'), exceptions))
    args += ['0.bst']

    result = cli.run(project=project, args=args, silent=True)
    result.assert_main_error(ErrorDomain.PIPELINE, "inconsistent-pipeline")


# Assert that if a build element has a dependency in the tracking
# queue it does not start building before tracking finishes.
@pytest.mark.datafiles(os.path.join(DATA_DIR))
@pytest.mark.parametrize("strict", ['--strict', '--no-strict'])
def test_build_track_track_first(cli, datafiles, tmpdir, strict):
    project = str(datafiles)
    dev_files_path = os.path.join(project, 'files', 'dev-files')
    element_path = os.path.join(project, 'elements')

    repo = create_repo('git', str(tmpdir))
    ref = repo.create(dev_files_path)

    create_elements = {
        '0.bst': [
            '1.bst'
        ],
        '1.bst': [],
        '2.bst': [
            '0.bst'
        ]
    }
    for element, dependencies in create_elements.items():
        # We set a ref so that 0.bst can already be built even if
        # 1.bst has not been tracked yet.
        create_element(repo, element, element_path, dependencies, ref=ref)
        repo.add_commit()

    # Build 1.bst and 2.bst first so we have an artifact for them
    args = [strict, 'build', '2.bst']
    result = cli.run(args=args, project=project, silent=True)
    result.assert_success()

    # Test building 0.bst while tracking 1.bst
    cli.remove_artifact_from_cache(project, '0.bst')

    args = [strict, 'build', '--track', '1.bst', '2.bst']
    result = cli.run(args=args, project=project, silent=True)
    result.assert_success()

    # Assert that 1.bst successfully tracks before 0.bst builds
    track_messages = re.finditer(r'\[track:1.bst\s*]', result.stderr)
    build_0 = re.search(r'\[\s*build:0.bst\s*] START', result.stderr).start()
    assert all(track_message.start() < build_0 for track_message in track_messages)

    # Assert that 2.bst is *only* rebuilt if we are in strict mode
    build_2 = re.search(r'\[\s*build:2.bst\s*] START', result.stderr)
    if strict == '--strict':
        assert build_2 is not None
    else:
        assert build_2 is None
