#
#  Copyright (C) 2019 Bloomberg Finance LP
#
#  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:
#        James Ennis <james.ennis@codethink.co.uk>

from typing import TYPE_CHECKING

from . import Element
from . import _cachekey
from ._exceptions import ArtifactElementError
from ._loader.metaelement import MetaElement
from .types import Scope

if TYPE_CHECKING:
    from typing import Dict


# ArtifactElement()
#
# Object to be used for directly processing an artifact
#
# Args:
#    context (Context): The Context object
#    ref (str): The artifact ref
#
class ArtifactElement(Element):

    # A hash of ArtifactElement by ref
    __instantiated_artifacts = {}   # type: Dict[str, ArtifactElement]

    # ArtifactElement's require this as the sandbox will use a normal
    # directory when we checkout
    BST_VIRTUAL_DIRECTORY = True

    def __init__(self, context, ref):
        _, element, key = verify_artifact_ref(ref)

        self._ref = ref
        self._key = key

        project = context.get_toplevel_project()
        meta = MetaElement(project, element)  # NOTE element has no .bst suffix
        plugin_conf = None

        super().__init__(context, project, meta, plugin_conf)

    # _new_from_artifact_ref():
    #
    # Recursively instantiate a new ArtifactElement instance, and its
    # dependencies from an artifact ref
    #
    # Args:
    #    ref (String): The artifact ref
    #    context (Context): The Context object
    #    task (Task): A task object to report progress to
    #
    # Returns:
    #    (ArtifactElement): A newly created Element instance
    #
    @classmethod
    def _new_from_artifact_ref(cls, ref, context, task=None):

        if ref in cls.__instantiated_artifacts:
            return cls.__instantiated_artifacts[ref]

        artifact_element = ArtifactElement(context, ref)
        # XXX: We need to call update state as it is responsible for
        # initialising an Element/ArtifactElement's Artifact (__artifact)
        artifact_element._update_state()
        cls.__instantiated_artifacts[ref] = artifact_element

        for dep_ref in artifact_element.get_dependency_refs(Scope.BUILD):
            dependency = ArtifactElement._new_from_artifact_ref(dep_ref, context, task)
            artifact_element._add_build_dependency(dependency)

        return artifact_element

    # _clear_artifact_refs_cache()
    #
    # Clear the internal artifact refs cache
    #
    # When loading ArtifactElements from artifact refs, we cache already
    # instantiated ArtifactElements in order to not have to load the same
    # ArtifactElements twice. This clears the cache.
    #
    # It should be called whenever we are done loading all artifacts in order
    # to save memory.
    #
    @classmethod
    def _clear_artifact_refs_cache(cls):
        cls.__instantiated_artifacts = {}

    # Override Element.get_artifact_name()
    def get_artifact_name(self, key=None):
        return self._ref

    # Dummy configure method
    def configure(self, node):
        pass

    # Dummy preflight method
    def preflight(self):
        pass

    # get_dependency_refs()
    #
    # Obtain the refs of a particular scope of dependencies
    #
    # Args:
    #   scope (Scope): The scope of dependencies for which we want to obtain the refs
    #
    # Returns:
    #   (list [str]): A list of artifact refs
    #
    def get_dependency_refs(self, scope=Scope.BUILD):
        artifact = self._get_artifact()
        return artifact.get_dependency_refs(deps=scope)

    # configure_sandbox()
    #
    # Configure a sandbox for installing artifacts into
    #
    # Args:
    #    sandbox (Sandbox)
    #
    def configure_sandbox(self, sandbox):
        install_root = self.get_variable('install-root')

        # Tell the sandbox to mount the build root and install root
        sandbox.mark_directory(install_root)

        # Tell sandbox which directory is preserved in the finished artifact
        sandbox.set_output_directory(install_root)

    # Override Element._calculate_cache_key
    def _calculate_cache_key(self, dependencies=None):
        return self._key

    # Override Element._get_cache_key()
    def _get_cache_key(self, strength=None):
        return self._key


# verify_artifact_ref()
#
# Verify that a ref string matches the format of an artifact
#
# Args:
#    ref (str): The artifact ref
#
# Returns:
#    project (str): The project's name
#    element (str): The element's name
#    key (str): The cache key
#
# Raises:
#    ArtifactElementError if the ref string does not match
#    the expected format
#
def verify_artifact_ref(ref):
    try:
        project, element, key = ref.split('/', 2)  # This will raise a Value error if unable to split
        # Explicitly raise a ValueError if the key length is not as expected
        if not _cachekey.is_key(key):
            raise ValueError
    except ValueError:
        raise ArtifactElementError("Artifact: {} is not of the expected format".format(ref))

    return project, element, key
