#
#  Copyright (C) 2018 Codethink Limited
#
#  This program is free software; you can redistribute it and/or
#  modify it under the terms of the GNU Lesser General Public
#  License as published by the Free Software Foundation; either
#  version 2 of the License, or (at your option) any later version.
#
#  This library is distributed in the hope that it will be useful,
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the GNU
#  Lesser General Public License for more details.
#
#  You should have received a copy of the GNU Lesser General Public
#  License along with this library. If not, see <http://www.gnu.org/licenses/>.
#
#  Authors:
#        Tristan Van Berkom <tristan.vanberkom@codethink.co.uk>

import os
from contextlib import suppress

from .._exceptions import LoadError
from ..exceptions import LoadErrorReason
from .. import _yaml
from ..element import Element
from ..node import Node
from .._profile import Topics, PROFILER
from .._includes import Includes
from .._utils import valid_chars_name
from ..types import _KeyStrength

from .types import Symbol
from . import loadelement
from .loadelement import LoadElement, Dependency, DependencyType, extract_depends_from_node


# Loader():
#
# The Loader class does the heavy lifting of parsing target
# bst files and ultimately transforming them into a list of LoadElements
# ready for instantiation by the core.
#
# Args:
#    project (Project): The toplevel Project object
#    parent (Loader): A parent Loader object, in the case this is a junctioned Loader
#    provenance_node (Node): The provenance of the reference to this project's junction
#
class Loader:
    def __init__(self, project, *, parent=None, provenance_node=None):

        # Ensure we have an absolute path for the base directory
        basedir = project.element_path
        if not os.path.isabs(basedir):
            basedir = os.path.abspath(basedir)

        #
        # Public members
        #
        self.load_context = project.load_context  # The LoadContext
        self.project = project  # The associated Project
        self.provenance_node = provenance_node  # The provenance of whence this loader was instantiated
        self.loaded = None  # The number of loaded Elements

        #
        # Private members
        #
        self._options = project.options  # Project options (OptionPool)
        self._basedir = basedir  # Base project directory
        self._first_pass_options = project.first_pass_config.options  # Project options (OptionPool)
        self._parent = parent  # The parent loader
        self._alternative_parents = []  # Overridden parent loaders

        self._meta_elements = {}  # Dict of resolved meta elements by name
        self._elements = {}  # Dict of elements
        self._links = {}  # Dict of link target target paths indexed by link element paths
        self._loaders = {}  # Dict of junction loaders
        self._loader_search_provenances = {}  # Dictionary of provenance nodes of ongoing child loader searches

        self._includes = Includes(self, copy_tree=True)

        assert project.name is not None

        self.load_context.register_loader(self)

    # The __str__ of a Loader is used to clearly identify the Loader,
    # the junction is was loaded as, and the provenance causing the
    # junction to be loaded.
    #
    def __str__(self):
        project_name = self.project.name

        if self.project.junction:
            junction_name = self.project.junction._get_full_name()
            if self.provenance_node:
                provenance = "({}): {}".format(junction_name, self.provenance_node.get_provenance())
            else:
                provenance = "({})".format(junction_name)
        else:
            provenance = "(toplevel)"

        return "{} {}".format(project_name, provenance)

    # load():
    #
    # Loads the project based on the parameters given to the constructor
    #
    # Args:
    #    targets (list of str): Target, element-path relative bst filenames in the project
    #
    # Raises: LoadError
    #
    # Returns:
    #    (list): The corresponding LoadElement instances matching the `targets`
    #
    def load(self, targets):

        for filename in targets:
            if os.path.isabs(filename):
                # XXX Should this just be an assertion ?
                # Expect that the caller gives us the right thing at least ?
                raise LoadError(
                    "Target '{}' was not specified as a relative "
                    "path to the base project directory: {}".format(filename, self._basedir),
                    LoadErrorReason.INVALID_DATA,
                )

        # First pass, recursively load files and populate our table of LoadElements
        #
        target_elements = []

        for target in targets:
            with PROFILER.profile(Topics.LOAD_PROJECT, target):
                _junction, name, loader = self._parse_name(target, None)
                element = loader._load_file(name, None)
                target_elements.append(element)

        #
        # Now that we've resolved the dependencies, scan them for circular dependencies
        #

        # Set up a dummy element that depends on all top-level targets
        # to resolve potential circular dependencies between them
        dummy_target = LoadElement(Node.from_dict({}), "", self)

        # Pylint is not very happy with Cython and can't understand 'dependencies' is a list
        dummy_target.dependencies.extend(  # pylint: disable=no-member
            Dependency(element, DependencyType.RUNTIME) for element in target_elements
        )

        with PROFILER.profile(Topics.CIRCULAR_CHECK, "_".join(targets)):
            self._check_circular_deps(dummy_target)

        #
        # Sort direct dependencies of elements by their dependency ordering
        #

        # Keep a list of all visited elements, to not sort twice the same
        visited_elements = set()

        for element in target_elements:
            loader = element._loader
            with PROFILER.profile(Topics.SORT_DEPENDENCIES, element.name):
                loadelement.sort_dependencies(element, visited_elements)

        self._clean_caches()

        # Cache how many Elements have just been loaded
        if self.load_context.task:
            self.loaded = self.load_context.task.current_progress

        return target_elements

    # get_loader():
    #
    # Obtains the appropriate loader for the specified junction
    #
    # If `load_subprojects` is enabled, then this function will
    # either return the desired loader or raise a LoadError. If
    # `load_subprojects` is disabled, then it can also return None
    # in the case that a loader could not be found. In either case,
    # a non-existant file in a loaded project will result in a LoadError.
    #
    # Args:
    #   name (str): Name of junction, may have multiple `:` in the name
    #   provenance_node (Node): The provenance from where this loader was requested
    #   load_subprojects (bool): Whether to load subprojects on demand
    #
    # Returns:
    #   (Loader): loader for sub-project
    #
    def get_loader(self, name, provenance_node, *, load_subprojects=True):
        junction_path = name.split(":")
        loader = self

        circular_provenance_node = self._loader_search_provenances.get(name, None)
        if circular_provenance_node and load_subprojects:

            assert provenance_node

            detail = None
            if circular_provenance_node is not provenance_node:
                detail = "Already searching for '{}' at: {}".format(name, circular_provenance_node.get_provenance())
            raise LoadError(
                "{}: Circular reference while searching for '{}'".format(provenance_node.get_provenance(), name),
                LoadErrorReason.CIRCULAR_REFERENCE,
                detail=detail,
            )

        if load_subprojects:
            self._loader_search_provenances[name] = provenance_node

        for junction_name in junction_path:
            loader = loader._get_loader(junction_name, provenance_node, load_subprojects=load_subprojects)

        if load_subprojects:
            del self._loader_search_provenances[name]

        return loader

    # ancestors()
    #
    # This will traverse all active loaders in the ancestry for which this
    # project is reachable using a relative path.
    #
    # Yields:
    #     (Loader): Each loader in the ancestry
    #
    def ancestors(self):
        traversed = {}

        def foreach_parent(parent):
            while parent:
                if parent in traversed:
                    return
                traversed[parent] = True
                yield parent
                parent = parent._parent

        # Yield from the direct/active ancestry
        yield from foreach_parent(self._parent)

        # Yield from alternative parents which have been replaced by
        # overrides in the ancestry.
        for parent in self._alternative_parents:
            yield from foreach_parent(parent)

    ###########################################
    #            Private Methods              #
    ###########################################

    # _load_file_no_deps():
    #
    # Load a bst file as a LoadElement
    #
    # This loads a bst file into a LoadElement but does no work to resolve
    # the element's dependencies.  The dependencies must be resolved properly
    # before the LoadElement makes its way out of the loader.
    #
    # Args:
    #    filename (str): The element-path relative bst file
    #    provenance_node (Node): The location from where the file was referred to, or None
    #
    # Returns:
    #    (LoadElement): A partially-loaded LoadElement
    #
    def _load_file_no_deps(self, filename, provenance_node=None):

        self._assert_element_name(filename, provenance_node)

        # Load the data and process any conditional statements therein
        fullpath = os.path.join(self._basedir, filename)
        try:
            node = _yaml.load(
                fullpath, shortname=filename, copy_tree=self.load_context.rewritable, project=self.project
            )
        except LoadError as e:
            if e.reason == LoadErrorReason.MISSING_FILE:

                if self.project.junction:
                    message = "Could not find element '{}' in project referred to by junction element '{}'".format(
                        filename, self.project.junction.name
                    )
                else:
                    message = "Could not find element '{}' in elements directory '{}'".format(filename, self._basedir)

                if provenance_node:
                    message = "{}: {}".format(provenance_node.get_provenance(), message)

                # If we can't find the file, try to suggest plausible
                # alternatives by stripping the element-path from the given
                # filename, and verifying that it exists.
                detail = None
                elements_dir = os.path.relpath(self._basedir, self.project.directory)
                element_relpath = os.path.relpath(filename, elements_dir)
                if filename.startswith(elements_dir) and os.path.exists(os.path.join(self._basedir, element_relpath)):
                    detail = "Did you mean '{}'?".format(element_relpath)

                raise LoadError(message, LoadErrorReason.MISSING_FILE, detail=detail) from e

            # Otherwise, we don't know the reason, so just raise
            raise

        kind = node.get_str(Symbol.KIND)
        if kind in ("junction", "link"):
            self._first_pass_options.process_node(node)
        else:
            self.project.ensure_fully_loaded()

            self._includes.process(node)

        element = LoadElement(node, filename, self)

        self._elements[filename] = element

        #
        # Update link caches in the ancestry
        #
        if element.link_target is not None:
            link_path = filename
            target_path = element.link_target.as_str()  # pylint: disable=no-member

            # First resolve the link in this loader's cache
            #
            self._resolve_link(link_path, target_path)

            # Now resolve the link in parent project loaders
            #
            loader = self
            while loader._parent:
                junction = loader.project.junction
                link_path = junction.name + ":" + link_path
                target_path = junction.name + ":" + target_path

                # Resolve the link
                loader = loader._parent
                loader._resolve_link(link_path, target_path)

        return element

    # _resolve_link():
    #
    # Resolves a link in the loader's link cache.
    #
    # This will first insert the new link -> target relationship
    # into the cache, and will also update any existing targets
    # which might have pointed to this link, to point to the new
    # target instead.
    #
    # Args:
    #    link_path (str): The local project relative real path to a link
    #    target_path (str): The new target for this link
    #
    def _resolve_link(self, link_path, target_path):
        self._links[link_path] = target_path

        for cached_link_path, cached_target_path in self._links.items():
            if self._expand_link(cached_target_path) == link_path:
                self._links[cached_link_path] = target_path

    # _expand_link():
    #
    # Expands any links in the provided path and returns a real path with
    # known link elements substituted for their targets.
    #
    # Args:
    #    path (str): A project relative path
    #
    # Returns:
    #    (str): The same path with any links expanded
    #
    def _expand_link(self, path):

        # FIXME: This simply returns the first link, maybe
        #        this needs to be more iterative, or sorted by
        #        number of path components, or smth
        for link, target in self._links.items():
            if path.startswith(link):
                return target + path[len(link) :]

        return path

    # _load_one_file():
    #
    # A helper function to load a single file within the _load_file() process,
    # this allows us to handle redirections more consistently.
    #
    # Args:
    #    filename (str): The element-path relative bst file
    #    provenance_node (Node): The location from where the file was referred to, or None
    #    load_subprojects (bool): Whether to load subprojects
    #
    # Returns:
    #    (LoadElement): A LoadElement, which might be shallow loaded or fully loaded.
    #
    def _load_one_file(self, filename, provenance_node, *, load_subprojects=True):

        element = None

        # First check the cache, the cache might contain shallow loaded
        # elements.
        #
        try:
            element = self._elements[filename]

            # If the cached element has already entered the loop which loads
            # it's dependencies, it is fully loaded and any further checks in
            # this function are expected to have already been performed.
            #
            if element.fully_loaded:
                return element

        except KeyError:

            # Shallow load if it's not yet loaded.
            element = self._load_file_no_deps(filename, provenance_node)

        # Check if there was an override for this element
        #
        override = self._search_for_override_element(filename)
        if override:
            #
            # If there was an override for the element, then it was
            # implicitly fully loaded by _search_for_override_element(),
            #
            return override

        # If this element is a link then we need to resolve it, and return
        # the linked element instead of this one.
        #
        if element.link_target is not None:
            link_target = element.link_target.as_str()  # pylint: disable=no-member
            _, filename, loader = self._parse_name(link_target, element.link_target, load_subprojects=load_subprojects)

            #
            # Redirect the loading of the file and it's dependencies to the appropriate loader,
            # which might or might not be the same loader.
            #
            return loader._load_file(filename, element.link_target, load_subprojects=load_subprojects)

        return element

    # _load_file():
    #
    # Semi-Iteratively load bst files
    #
    # The "Semi-" qualification is because where junctions get involved there
    # is a measure of recursion, though this is limited only to the points at
    # which junctions are crossed.
    #
    # Args:
    #    filename (str): The element-path relative bst file
    #    provenance_node (Node): The location from where the file was referred to, or None
    #    load_subprojects (bool): Whether to load subprojects
    #
    # Returns:
    #    (LoadElement): A loaded LoadElement
    #
    def _load_file(self, filename, provenance_node, *, load_subprojects=True):

        top_element = self._load_one_file(filename, provenance_node, load_subprojects=load_subprojects)

        # Already loaded dependencies for a fully loaded element, early return.
        #
        if top_element.fully_loaded:
            return top_element

        #
        # Mark the top element here as "fully loaded", so that we will avoid trying to
        # load it's dependencies more than once.
        #
        top_element.mark_fully_loaded()

        dependencies = extract_depends_from_node(top_element.node)
        # The loader queue is a stack of tuples
        # [0] is the LoadElement instance
        # [1] is a stack of Dependency objects to load
        # [2] is a list of dependency names used to warn when all deps are loaded
        loader_queue = [(top_element, list(reversed(dependencies)), [])]

        # Load all dependency files for the new LoadElement
        while loader_queue:
            if loader_queue[-1][1]:
                current_element = loader_queue[-1]

                # Process the first dependency of the last loaded element
                dep = current_element[1].pop()
                # And record its name for checking later
                current_element[2].append(dep.name)

                if dep.junction:
                    loader = self.get_loader(dep.junction, dep.node)
                    dep_element = loader._load_file(dep.name, dep.node)

                else:

                    dep_element = self._load_one_file(dep.name, dep.node, load_subprojects=load_subprojects)

                    # If the loaded element is not fully loaded, queue up the dependencies to be loaded in this loop.
                    #
                    if not dep_element.fully_loaded:

                        # Mark the dep_element as fully_loaded, as we're already queueing it's deps
                        dep_element.mark_fully_loaded()

                        dep_deps = extract_depends_from_node(dep_element.node)
                        loader_queue.append((dep_element, list(reversed(dep_deps)), []))

                        # Pylint is not very happy about Cython and can't understand 'node' is a 'MappingNode'
                        if dep_element.node.get_str(Symbol.KIND) == "junction":  # pylint: disable=no-member
                            raise LoadError(
                                "{}: Cannot depend on junction".format(dep.node.get_provenance()),
                                LoadErrorReason.INVALID_DATA,
                            )

                # We've now resolved the element for this dependency, lets set the resolved
                # LoadElement on the dependency and append the dependency to the owning
                # LoadElement dependency list.
                dep.set_element(dep_element)
                current_element[0].dependencies.append(dep)  # pylint: disable=no-member
            else:
                # And pop the element off the queue
                loader_queue.pop()

        # Nothing more in the queue, return the top level element we loaded.
        return top_element

    # _check_circular_deps():
    #
    # Detect circular dependencies on LoadElements with
    # dependencies already resolved.
    #
    # Args:
    #    element (str): The element to check
    #
    # Raises:
    #    (LoadError): In case there was a circular dependency error
    #
    @staticmethod
    def _check_circular_deps(top_element):

        sequence = [top_element]
        sequence_indices = [0]
        check_elements = set(sequence)
        validated = set()

        while sequence:
            this_element = sequence[-1]
            index = sequence_indices[-1]
            if index < len(this_element.dependencies):
                element = this_element.dependencies[index].element
                sequence_indices[-1] = index + 1
                if element in check_elements:
                    # Create `chain`, the loop of element dependencies from this
                    # element back to itself, by trimming everything before this
                    # element from the sequence under consideration.
                    chain = [element.full_name for element in sequence[sequence.index(element) :]]
                    chain.append(element.full_name)
                    raise LoadError(
                        ("Circular dependency detected at element: {}\n" + "Dependency chain: {}").format(
                            element.full_name, " -> ".join(chain)
                        ),
                        LoadErrorReason.CIRCULAR_DEPENDENCY,
                    )
                if element not in validated:
                    # We've not already validated this element, so let's
                    # descend into it to check it out
                    sequence.append(element)
                    sequence_indices.append(0)
                    check_elements.add(element)
                # Otherwise we'll head back around the loop to validate the
                # next dependency in this entry
            else:
                # Done with entry, pop it off, indicate we're no longer
                # in its chain, and mark it valid
                sequence.pop()
                sequence_indices.pop()
                check_elements.remove(this_element)
                validated.add(this_element)

    # _search_for_local_override():
    #
    # Search this project's active override list for an override, while
    # considering any link elements.
    #
    # Args:
    #    override_path (str): The real relative path to search for
    #
    # Returns:
    #    (ScalarNode): The overridding node from this project's junction, or None
    #
    def _search_for_local_override(self, override_path):
        junction = self.project.junction
        if junction is None:
            return None

        # Try the override without any link substitutions first
        with suppress(KeyError):
            return junction.overrides[override_path]

        #
        # If we did not get an exact match here, we might still have
        # an override where a link was used to specify the override.
        #
        for override_key, override_node in junction.overrides.items():
            resolved_path = self._expand_link(override_key)
            if resolved_path == override_path:
                return override_node

        return None

    # _search_for_overrides():
    #
    # Search for parent loaders which have an override for the specified element,
    # returning a list of loaders with the highest level overriding loader at the
    # end of the list, and the closest ancestor being at the beginning of the list.
    #
    # Args:
    #    filename (str): The local element name
    #
    # Returns:
    #    (list): A list of loaders which override this element
    #
    def _search_for_overrides(self, filename):
        loader = self
        override_path = filename

        # Collect any overrides to this junction in the ancestry
        #
        overriding_loaders = []
        while loader._parent:
            junction = loader.project.junction
            override_node = loader._search_for_local_override(override_path)
            if override_node:
                overriding_loaders.append((loader._parent, override_node))

            override_path = junction.name + ":" + override_path
            loader = loader._parent

        return overriding_loaders

    # _search_for_override_loader():
    #
    # Search parent projects an override of the junction specified by @filename,
    # returning the loader object which should be used in place of the local
    # junction specified by @filename.
    #
    # This function is called once for each direct child while looking up
    # child loaders, after which point the child loader is cached in the `_loaders`
    # table. This function also has the side effect of recording alternative parents
    # of a child loader in the case that the child loader is overridden.
    #
    # Args:
    #    filename (str): Junction name
    #
    # Returns:
    #    (Loader): The loader to use, in case @filename was overridden, otherwise None.
    #
    def _search_for_override_loader(self, filename):

        overriding_loaders = self._search_for_overrides(filename)

        # If there are any overriding loaders, use the highest one in
        # the ancestry to lookup the loader for this project.
        #
        if overriding_loaders:
            overriding_loader, override_node = overriding_loaders[-1]
            loader = overriding_loader.get_loader(override_node.as_str(), override_node)

            #
            # Record alternative loaders which were overridden.
            #
            # When a junction is overridden by another higher priority junction,
            # the resulting loader is still reachable with the original element paths,
            # which will now traverse override redirections.
            #
            # In order to iterate over every project/loader in the ancestry which can
            # reach the actually selected loader, we need to keep track of the parent
            # loaders of all overridden junctions.
            #
            if loader is not self:
                loader._alternative_parents.append(self)

            del overriding_loaders[-1]
            loader._alternative_parents.extend(l for l, _ in overriding_loaders)

            return loader

        # No overrides were found in the ancestry
        #
        return None

    # _search_for_override_element():
    #
    # Search parent projects an override of the element specified by @filename,
    # returning the loader object which should be used in place of the local
    # element specified by @filename.
    #
    # Args:
    #    filename (str): Junction name
    #
    # Returns:
    #    (Loader): The loader to use, in case @filename was overridden, otherwise None.
    #
    def _search_for_override_element(self, filename):
        element = None

        # If there are any overriding loaders, use the highest one in
        # the ancestry to lookup the element which should be used in place
        # of @filename.
        #
        overriding_loaders = self._search_for_overrides(filename)
        if overriding_loaders:
            overriding_loader, override_node = overriding_loaders[-1]

            _, filename, loader = overriding_loader._parse_name(override_node.as_str(), override_node)
            element = loader._load_file(filename, override_node)

        return element

    # _get_loader():
    #
    # Return loader for specified junction
    #
    # Args:
    #    filename (str): Junction name
    #    load_subprojects (bool): Whether to load subprojects
    #    provenance_node (Node): The location from where the file was referred to, or None
    #
    # Raises: LoadError
    #
    # Returns: A Loader or None if specified junction does not exist
    #
    def _get_loader(self, filename, provenance_node, *, load_subprojects=True):
        loader = None

        # return previously determined result
        if filename in self._loaders:
            return self._loaders[filename]

        # Local function to conditionally resolve the provenance prefix string
        def provenance_str():
            if provenance_node is not None:
                return "{}: ".format(provenance_node.get_provenance())
            return ""

        #
        # Search the ancestry for an overridden loader to use in place
        # of using the locally defined junction.
        #
        override_loader = self._search_for_override_loader(filename)
        if override_loader:
            self._loaders[filename] = override_loader
            return override_loader

        #
        # Load the junction file
        #
        self._load_file(filename, provenance_node, load_subprojects=load_subprojects)

        # At this point we've loaded the LoadElement
        load_element = self._elements[filename]

        # If the loaded element is a link, then just follow it
        # immediately and move on to the target.
        #
        if load_element.link_target:
            _, filename, loader = self._parse_name(
                load_element.link_target.as_str(), load_element.link_target, load_subprojects=load_subprojects
            )
            return loader.get_loader(filename, load_element.link_target, load_subprojects=load_subprojects)

        # If we're only performing a lookup, we're done here.
        #
        if not load_subprojects:
            return None

        if load_element.kind != "junction":
            raise LoadError(
                "{}{}: Expected junction but element kind is {}".format(provenance_str(), filename, load_element.kind),
                LoadErrorReason.INVALID_DATA,
            )

        # We check that junctions have no dependencies a little
        # early. This is cheating, since we don't technically know
        # that junctions aren't allowed to have dependencies.
        #
        # However, this makes progress reporting more intuitive
        # because we don't need to load dependencies of an element
        # that shouldn't have any, and therefore don't need to
        # duplicate the load count for elements that shouldn't be.
        #
        # We also fail slightly earlier (since we don't need to go
        # through the entire loading process), which is nice UX. It
        # would be nice if this could be done for *all* element types,
        # but since we haven't loaded those yet that's impossible.
        if load_element.dependencies:
            # Use the first dependency in the list as provenance
            p = load_element.dependencies[0].node.get_provenance()
            raise LoadError(
                "{}: Dependencies are forbidden for 'junction' elements".format(p), LoadErrorReason.INVALID_JUNCTION
            )

        element = Element._new_from_load_element(load_element)

        # Handle the case where a subproject has no ref
        #
        if not element._has_all_sources_resolved():
            detail = "Try tracking the junction element with `bst source track {}`".format(filename)
            raise LoadError(
                "{}Subproject has no ref for junction: {}".format(provenance_str(), filename),
                LoadErrorReason.SUBPROJECT_INCONSISTENT,
                detail=detail,
            )

        # Handle the case where a subproject needs to be fetched
        #
        element._query_source_cache()
        if element._should_fetch():
            self.load_context.fetch_subprojects([element])

        sources = list(element.sources())
        if len(sources) == 1 and sources[0]._get_local_path():
            # Optimization for junctions with a single local source
            basedir = sources[0]._get_local_path()
        else:
            # Stage sources
            element._set_required()

            # Note: We use _KeyStrength.WEAK here because junctions
            # cannot have dependencies, therefore the keys are
            # equivalent.
            #
            # Since the element has not necessarily been given a
            # strong cache key at this point (in a non-strict build
            # that is set *after* we complete building/pulling, which
            # we haven't yet for this element),
            # element._get_cache_key() can fail if used with the
            # default _KeyStrength.STRONG.
            basedir = os.path.join(
                self.project.directory, ".bst", "staged-junctions", filename, element._get_cache_key(_KeyStrength.WEAK)
            )
            if not os.path.exists(basedir):
                os.makedirs(basedir, exist_ok=True)
                element._stage_sources_at(basedir)

        # Load the project
        project_dir = os.path.join(basedir, element.path)
        try:
            from .._project import Project  # pylint: disable=cyclic-import

            project = Project(
                project_dir,
                self.load_context.context,
                junction=element,
                parent_loader=self,
                search_for_project=False,
                provenance_node=provenance_node,
            )
        except LoadError as e:
            if e.reason == LoadErrorReason.MISSING_PROJECT_CONF:
                message = provenance_str() + "Could not find the project.conf file in the project " "referred to by junction element '{}'.".format(
                    element.name
                )
                if element.path:
                    message += " Was expecting it at path '{}' in the junction's source.".format(element.path)
                raise LoadError(message=message, reason=LoadErrorReason.INVALID_JUNCTION) from e

            # Otherwise, we don't know the reason, so just raise
            raise

        loader = project.loader
        self._loaders[filename] = loader

        # Now we've loaded a junction and it's project, we need to try to shallow
        # load the overrides of this project and any projects in the ancestry which
        # have overrides referring to this freshly loaded project.
        #
        # This is to ensure that link elements have been resolved as much as possible
        # before we try to look for an override.
        #
        iter_loader = loader
        while iter_loader._parent:
            iter_loader._shallow_load_overrides()
            iter_loader = iter_loader._parent

        return loader

    # _shallow_load_overrides():
    #
    # Loads any of the override elements on this loader's junction
    #
    def _shallow_load_overrides(self):
        if not self.project.junction:
            return

        junction = self.project.junction

        # Iterate over the keys, we want to ensure that links are resolved for
        # override paths specified in junctions, while the targets of these paths
        # are not consequential.
        #
        for override_path, override_target in junction.overrides.items():

            # Ensure that we resolve indirect links, in case that shallow loading
            # an element results in loading a link, we need to discover if it's
            # target is also a link.
            #
            path = override_path
            provenance_node = override_target
            while path is not None:
                path, provenance_node = self._shallow_load_path(path, provenance_node)

    # _shallow_load_path()
    #
    # Perform a shallow load of an element by it's relative path, this is
    # used to load elements which might be specified by their path and might
    # not be used in the resulting load, like paths to elements overridden by
    # junctions.
    #
    # It is only important to shallow load these referenced elements in case
    # they are links which need to be known later on.
    #
    # Args:
    #    path (str): The path to load
    #    provenance_node (Node): The node to use for provenance
    #
    # Returns:
    #    (str): The target of the loaded link element, if it was a link element
    #           and it could be loaded presently, otherwise None.
    #    (ScalarNode): The link target real node, if a link target was returned
    #
    def _shallow_load_path(self, path, provenance_node):
        if ":" in path:
            junction, element_name = path.rsplit(":", 1)
            target_loader = self.get_loader(junction, provenance_node, load_subprojects=False)

            # Subproject not loaded, discard this shallow load attempt
            #
            if target_loader is None:
                return None, None
        else:
            junction = None
            element_name = path
            target_loader = self

        # If the element is already loaded in the target loader, then there
        # is no need for a shallow load.
        try:
            element = target_loader._elements[element_name]
        except KeyError:
            # Shallow load the the element.
            element = target_loader._load_file_no_deps(element_name, provenance_node)

        if element.link_target:
            link_target = element.link_target.as_str()
            if junction:
                return "{}:{}".format(junction, link_target), element.link_target

            return link_target, element.link_target

        return None, None

    # _parse_name():
    #
    # Get junction and base name of element along with loader for the sub-project
    #
    # Args:
    #   name (str): Name of target
    #   provenance_node (Node): The provenance node
    #   load_subprojects (bool): Whether to load subprojects
    #
    # Returns:
    #   (tuple): - (str): name of the junction element
    #            - (str): name of the element
    #            - (Loader): loader for sub-project
    #
    def _parse_name(self, name, provenance_node, *, load_subprojects=True):
        # We allow to split only once since deep junctions names are forbidden.
        # Users who want to refer to elements in sub-sub-projects are required
        # to create junctions on the top level project.
        junction_path = name.rsplit(":", 1)
        if len(junction_path) == 1:
            return None, junction_path[-1], self
        else:
            loader = self.get_loader(junction_path[-2], provenance_node, load_subprojects=load_subprojects)
            return junction_path[-2], junction_path[-1], loader

    # _warn():
    #
    # Print a warning message, checks warning_token against project configuration
    #
    # Args:
    #     brief (str): The brief message
    #     warning_token (str): An optional configurable warning assosciated with this warning,
    #                          this will cause PluginError to be raised if this warning is configured as fatal.
    #
    # Raises:
    #     (:class:`.LoadError`): When warning_token is considered fatal by the project configuration
    #
    def _warn(self, brief, *, warning_token=None):
        if warning_token:
            if self.project._warning_is_fatal(warning_token):
                raise LoadError(brief, warning_token)

        self.load_context.context.messenger.warn(brief)

    # _assert_element_name():
    #
    # Raises an error if any of the specified elements have invalid names.
    #
    # Valid filenames should end with ".bst" extension.
    #
    # Args:
    #    filename (str): The element name
    #    provenance_node (Node): The provenance node, or None
    #
    # Raises:
    #     (:class:`.LoadError`): If the element name is invalid
    #
    def _assert_element_name(self, filename, provenance_node):
        error_message = None
        error_reason = None

        if not filename.endswith(".bst"):
            error_message = "Element '{}' does not have expected file extension `.bst`".format(filename)
            error_reason = LoadErrorReason.BAD_ELEMENT_SUFFIX
        elif not valid_chars_name(filename):
            error_message = "Element '{}' has invalid characters.".format(filename)
            error_reason = LoadErrorReason.BAD_CHARACTERS_IN_NAME

        if error_message:
            if provenance_node is not None:
                error_message = "{}: {}".format(provenance_node.get_provenance(), error_message)
            raise LoadError(error_message, error_reason)

    # _clean_caches()
    #
    # Clean internal loader caches, recursively
    #
    # When loading the elements, the loaders use caches in order to not load the
    # same element twice. These are kept after loading and prevent garbage
    # collection. Cleaning them explicitely is required.
    #
    def _clean_caches(self):
        for loader in self._loaders.values():
            # value may be None with nested junctions without overrides
            if loader is not None:
                loader._clean_caches()

        self._meta_elements = {}
        self._elements = {}
