#
#  Copyright (C) 2017 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:
#        Jonathan Maw <jonathan.maw@codethink.co.uk>

"""
ScriptElement - Abstract class for scripting elements
=====================================================
The ScriptElement class is a convenience class one can derive for
implementing elements that stage elements and run command-lines on them.

Any derived classes must write their own configure() implementation, using
the public APIs exposed in this class.

Derived classes must also chain up to the parent method in their preflight()
implementations.


"""

import os
from collections import OrderedDict

from . import Element, ElementError, Scope, SandboxFlags


class ScriptElement(Element):
    __install_root = "/"
    __cwd = "/"
    __root_read_only = False
    __commands = None
    __layout = []

    # The compose element's output is it's dependencies, so
    # we must rebuild if the dependencies change even when
    # not in strict build plans.
    #
    BST_STRICT_REBUILD = True

    # Script artifacts must never have indirect dependencies,
    # so runtime dependencies are forbidden.
    BST_FORBID_RDEPENDS = True

    # This element ignores sources, so we should forbid them from being
    # added, to reduce the potential for confusion
    BST_FORBID_SOURCES = True

    def set_work_dir(self, work_dir=None):
        """Sets the working dir

        The working dir (a.k.a. cwd) is the directory which commands will be
        called from.

        Args:
          work_dir (str): The working directory. If called without this argument
          set, it'll default to the value of the variable ``cwd``.
        """
        if work_dir is None:
            self.__cwd = self.get_variable("cwd") or "/"
        else:
            self.__cwd = work_dir

    def set_install_root(self, install_root=None):
        """Sets the install root

        The install root is the directory which output will be collected from
        once the commands have been run.

        Args:
          install_root(str): The install root. If called without this argument
          set, it'll default to the value of the variable ``install-root``.
        """
        if install_root is None:
            self.__install_root = self.get_variable("install-root") or "/"
        else:
            self.__install_root = install_root

    def set_root_read_only(self, root_read_only):
        """Sets root read-only

        When commands are run, if root_read_only is true, then the root of the
        filesystem will be protected. This is strongly recommended whenever
        possible.

        If this variable is not set, the default permission is read-write.

        Args:
          root_read_only (bool): Whether to mark the root filesystem as
          read-only.
        """
        self.__root_read_only = root_read_only

    def layout_add(self, element, destination):
        """Adds an element-destination pair to the layout.

        Layout is a way of defining how dependencies should be added to the
        staging area for running commands.

        Args:
          element (str): The name of the element to stage, or None. This may be any
                         element found in the dependencies, whether it is a direct
                         or indirect dependency.
          destination (str): The path inside the staging area for where to
                             stage this element. If it is not "/", then integration
                             commands will not be run.

        If this function is never called, then the default behavior is to just
        stage the Scope.BUILD dependencies of the element in question at the
        sandbox root. Otherwise, the Scope.RUN dependencies of each specified
        element will be staged in their specified destination directories.

        .. note::

           The order of directories in the layout is significant as they
           will be mounted into the sandbox. It is an error to specify a parent
           directory which will shadow a directory already present in the layout.

        .. note::

           In the case that no element is specified, a read-write directory will
           be made available at the specified location.
        """
        #
        # Even if this is an empty list by default, make sure that it's
        # instance data instead of appending stuff directly onto class data.
        #
        if not self.__layout:
            self.__layout = []
        self.__layout.append({"element": element,
                              "destination": destination})

    def add_commands(self, group_name, command_list):
        """Adds a list of commands under the group-name.

        .. note::

           Command groups will be run in the order they were added.

        .. note::

           This does not perform substitutions automatically. They must
           be performed beforehand (see
           :func:`~buildstream.element.Element.node_subst_list`)

        Args:
          group_name (str): The name of the group of commands.
          command_list (list): The list of commands to be run.
        """
        if not self.__commands:
            self.__commands = OrderedDict()
        self.__commands[group_name] = command_list

    def __validate_layout(self):
        if self.__layout:
            # Cannot proceeed if layout is used, but none are for "/"
            root_defined = any([(entry['destination'] == '/') for entry in self.__layout])
            if not root_defined:
                raise ElementError("{}: Using layout, but none are staged as '/'"
                                   .format(self))

            # Cannot proceed if layout specifies an element that isn't part
            # of the dependencies.
            for item in self.__layout:
                if item['element']:
                    if not self.search(Scope.BUILD, item['element']):
                        raise ElementError("{}: '{}' in layout not found in dependencies"
                                           .format(self, item['element']))

    def preflight(self):
        # The layout, if set, must make sense.
        self.__validate_layout()

    def get_unique_key(self):
        return {
            'commands': self.__commands,
            'cwd': self.__cwd,
            'install-root': self.__install_root,
            'layout': self.__layout,
            'root-read-only': self.__root_read_only
        }

    def configure_sandbox(self, sandbox):

        # Setup the environment and work directory
        sandbox.set_work_directory(self.__cwd)

        # Setup environment
        sandbox.set_environment(self.get_environment())

        # Tell the sandbox to mount the install root
        directories = {self.__install_root: False}

        # Mark the artifact directories in the layout
        for item in self.__layout:
            destination = item['destination']
            was_artifact = directories.get(destination, False)
            directories[destination] = item['element'] or was_artifact

        for directory, artifact in directories.items():
            # Root does not need to be marked as it is always mounted
            # with artifact (unless explicitly marked non-artifact)
            if directory != '/':
                sandbox.mark_directory(directory, artifact=artifact)

    def stage(self, sandbox):

        # Stage the elements, and run integration commands where appropriate.
        if not self.__layout:
            # if no layout set, stage all dependencies into /
            for build_dep in self.dependencies(Scope.BUILD, recurse=False):
                with self.timed_activity("Staging {} at /"
                                         .format(build_dep.name), silent_nested=True):
                    build_dep.stage_dependency_artifacts(sandbox, Scope.RUN, path="/")

            for build_dep in self.dependencies(Scope.BUILD, recurse=False):
                with self.timed_activity("Integrating {}".format(build_dep.name), silent_nested=True):
                    for dep in build_dep.dependencies(Scope.RUN):
                        dep.integrate(sandbox)
        else:
            # If layout, follow its rules.
            for item in self.__layout:

                # Skip layout members which dont stage an element
                if not item['element']:
                    continue

                element = self.search(Scope.BUILD, item['element'])
                if item['destination'] == '/':
                    with self.timed_activity("Staging {} at /".format(element.name),
                                             silent_nested=True):
                        element.stage_dependency_artifacts(sandbox, Scope.RUN)
                else:
                    with self.timed_activity("Staging {} at {}"
                                             .format(element.name, item['destination']),
                                             silent_nested=True):
                        real_dstdir = os.path.join(sandbox.get_directory(),
                                                   item['destination'].lstrip(os.sep))
                        os.makedirs(os.path.dirname(real_dstdir), exist_ok=True)
                        element.stage_dependency_artifacts(sandbox, Scope.RUN, path=item['destination'])

            for item in self.__layout:

                # Skip layout members which dont stage an element
                if not item['element']:
                    continue

                element = self.search(Scope.BUILD, item['element'])

                # Integration commands can only be run for elements staged to /
                if item['destination'] == '/':
                    with self.timed_activity("Integrating {}".format(element.name),
                                             silent_nested=True):
                        for dep in element.dependencies(Scope.RUN):
                            dep.integrate(sandbox)

        os.makedirs(os.path.join(sandbox.get_directory(), self.__install_root.lstrip(os.sep)),
                    exist_ok=True)

    def assemble(self, sandbox):

        for groupname, commands in self.__commands.items():
            with self.timed_activity("Running '{}'".format(groupname)):
                for cmd in commands:
                    self.status("Running command", detail=cmd)
                    # Note the -e switch to 'sh' means to exit with an error
                    # if any untested command fails.
                    exitcode = sandbox.run(['sh', '-c', '-e', cmd + '\n'],
                                           SandboxFlags.ROOT_READ_ONLY if self.__root_read_only else 0)
                    if exitcode != 0:
                        raise ElementError("Command '{}' failed with exitcode {}".format(cmd, exitcode))

        # Return where the result can be collected from
        return self.__install_root


def setup():
    return ScriptElement
