# Copyright 2018 The ChromiumOS Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

"""Choose the profile for a board that has been or is being setup."""

import functools
import logging
import os
from typing import Optional

from chromite.lib import build_target_lib
from chromite.lib import commandline
from chromite.lib import cros_build_lib
from chromite.lib import osutils
from chromite.lib import sysroot_lib


# Default value constants.
_DEFAULT_PROFILE = "base"


def PathPrefixDecorator(f):
    """Add a prefix to the path or paths returned by the decorated function.

    Will not prepend the prefix if the path already starts with the prefix, so
    the decorator may be applied to functions that have mixed sources that may
    or may not already have applied them. This is especially useful for allowing
    tests and CLI args a little more leniency in how paths are provided.
    """

    @functools.wraps(f)
    def wrapper(*args, **kwargs):
        result = f(*args, **kwargs)
        prefix = PathPrefixDecorator.prefix

        if not prefix or not result:
            # Nothing to do.
            return result

        # Convert Path objects to str.
        if isinstance(prefix, os.PathLike):
            prefix = str(prefix)

        if not isinstance(result, str):
            # Transform each path in the collection.
            new_result = []
            for path in result:
                prefixed_path = os.path.join(prefix, path.lstrip(os.sep))
                new_result.append(
                    path if path.startswith(prefix) else prefixed_path
                )

            return new_result
        elif not result.startswith(prefix):
            # Add the prefix.
            return os.path.join(prefix, result.lstrip(os.sep))

        # An already prefixed path.
        return result

    return wrapper


PathPrefixDecorator.prefix = None


class Error(Exception):
    """Base error for custom exceptions in this script."""


class InvalidArgumentsError(Error):
    """Invalid arguments."""


class MakeProfileIsNotLinkError(Error):
    """The make profile exists but is not a link."""


class ProfileDirectoryNotFoundError(Error):
    """Unable to find the profile directory."""


def ChooseProfile(board, profile) -> None:
    """Make the link to choose the profile, print relevant warnings.

    Args:
        board: Board - the board being used.
        profile: Profile - the profile being used.

    Raises:
        OSError when the board's make_profile path exists and is not a link.
    """
    if not os.path.isfile(os.path.join(profile.directory, "parent")):
        logging.warning(
            "Portage profile directory %s has no 'parent' file. "
            "This likely means your profile directory is invalid and "
            "`cros build-packages` will fail.",
            profile.directory,
        )

    current_profile = None
    if os.path.exists(board.make_profile):
        # Only try to read if it exists; we only want it to raise an error when
        # the path exists and is not a link.
        try:
            current_profile = os.readlink(board.make_profile)
        except OSError:
            raise MakeProfileIsNotLinkError(
                "%s is not a link." % board.make_profile
            )

    if current_profile == profile.directory:
        # The existing link is what we were going to make, so nothing to do.
        return
    elif current_profile is not None:
        # It exists and is changing, emit warning.
        fmt = {"board": board.board_variant, "profile": profile.name}
        msg = (
            "You are switching profiles for a board that is already setup. "
            "This can cause trouble for Portage. If you experience problems "
            "with `cros build-packages` you may need to run:\n"
            "\t'setup_board --board %(board)s --force --profile %(profile)s'\n"
            "\nAlternatively, you can correct the dependency graph by using "
            "'emerge-%(board)s -c' or 'emerge-%(board)s -C <ebuild>'."
        )
        logging.warning(msg, fmt)

    # Make the symlink, overwrites existing link if one already exists.
    osutils.SafeSymlink(profile.directory, board.make_profile, sudo=True)

    # Update the profile override value.
    if profile.override:
        board.profile_override = profile.override


class Profile:
    """Simple data container class for the profile data."""

    def __init__(self, name, directory, override) -> None:
        self.name = name
        self._directory = directory
        self.override = override

    @property
    @PathPrefixDecorator
    def directory(self):
        return self._directory


def _GetProfile(opts, board):
    """Get the profile list."""
    # Determine the override value - which profile is being selected.
    override = opts.profile if opts.profile else board.profile_override

    profile = _DEFAULT_PROFILE
    profile_directory = None

    if override and os.path.exists(override):
        profile_directory = os.path.abspath(override)
        profile = os.path.basename(profile_directory)
    elif override:
        profile = override

    if profile_directory is None:
        # Build profile directories in reverse order, so we can search from most
        # to least specific.
        profile_dirs = [
            "%s/profiles/%s" % (overlay, profile)
            for overlay in reversed(board.overlays)
        ]

        for profile_dir in profile_dirs:
            if os.path.isdir(profile_dir):
                profile_directory = profile_dir
                break
        else:
            searched = ", ".join(profile_dirs)
            raise ProfileDirectoryNotFoundError(
                "Profile directory not found, searched in (%s)." % searched
            )

    return Profile(profile, profile_directory, override)


class Board:
    """Manage the board arguments and configs."""

    # Files located on the board.
    MAKE_PROFILE = "%(board_root)s/etc/portage/make.profile"

    def __init__(
        self,
        board: Optional[str] = None,
        variant: Optional[str] = None,
        board_root: Optional[str] = None,
    ) -> None:
        """Board constructor.

        board [+ variant] is given preference when both board and board_root are
        provided.

        Preconditions:
            Either board and build_root are not None, or board_root is not None.
                With board + build_root we can construct the board root.
                With the board root we can have the board directory.

        Args:
            board: The board name.
            variant: The variant name. TODO: Deprecate?
            board_root: The boards fully qualified build directory path.
        """
        if not board and not board_root:
            # Enforce preconditions.
            raise InvalidArgumentsError(
                "Either board or board_root must be provided."
            )
        elif board:
            # The board and variant can be specified separately, or can both be
            # contained in the board name, separated by an underscore.
            board_split = board.split("_")
            variant_default = variant

            self._board_root = None
        else:
            self._board_root = os.path.normpath(board_root)

            board_split = os.path.basename(self._board_root).split("_")
            variant_default = None

        self.board = board_split.pop(0)
        self.variant = board_split.pop(0) if board_split else variant_default

        if self.variant:
            self.board_variant = "%s_%s" % (self.board, self.variant)
        else:
            self.board_variant = self.board

        self.make_profile = self.MAKE_PROFILE % {"board_root": self.root}
        # This must come after the arguments required to build each variant of
        # the build root have been processed.
        self._sysroot_config = sysroot_lib.Sysroot(self.root)

    @property
    @PathPrefixDecorator
    def root(self):
        if self._board_root:
            return self._board_root

        return build_target_lib.get_default_sysroot_path(self.board_variant)

    @property
    @PathPrefixDecorator
    def overlays(self):
        return self._sysroot_config.GetStandardField(
            sysroot_lib.STANDARD_FIELD_BOARD_OVERLAY
        ).split()

    @property
    def profile_override(self):
        return self._sysroot_config.GetCachedField("PROFILE_OVERRIDE")

    @profile_override.setter
    def profile_override(self, value) -> None:
        self._sysroot_config.SetCachedField("PROFILE_OVERRIDE", value)


def _GetBoard(opts):
    """Factory method to build a Board from the parsed CLI arguments."""
    return Board(
        board=opts.board, variant=opts.variant, board_root=opts.board_root
    )


def GetParser():
    """ArgumentParser builder and argument definitions."""
    parser = commandline.ArgumentParser(description=__doc__)
    parser.add_argument(
        "-b",
        "--board",
        default=os.environ.get("DEFAULT_BOARD"),
        help="The name of the board to set up.",
    )
    parser.add_argument(
        "-r",
        "--board-root",
        type="str_path",
        help="Board root where the profile should be created.",
    )
    parser.add_argument(
        "-p", "--profile", help="The portage configuration profile to use."
    )
    parser.add_argument("--variant", help="Board variant.")

    group = parser.add_argument_group("Advanced options")
    group.add_argument(
        "--filesystem-prefix",
        type="str_path",
        help="Force filesystem accesses to be prefixed by the given path.",
    )
    return parser


def ParseArgs(argv):
    """Parse and validate the arguments."""
    parser = GetParser()
    opts = parser.parse_args(argv)

    # See Board.__init__ Preconditions.
    board_valid = opts.board is not None
    board_root_valid = opts.board_root and os.path.exists(opts.board_root)

    if not board_valid and not board_root_valid:
        parser.error("Either board or board_root must be provided.")

    PathPrefixDecorator.prefix = opts.filesystem_prefix
    del opts.filesystem_prefix

    opts.Freeze()
    return opts


def main(argv) -> None:
    # Parse arguments.
    opts = ParseArgs(argv)

    # Build and validate the board and profile.
    board = _GetBoard(opts)

    if not os.path.exists(board.root):
        cros_build_lib.Die(
            "The board has not been setup, please run setup_board first."
        )

    try:
        profile = _GetProfile(opts, board)
    except ProfileDirectoryNotFoundError as e:
        cros_build_lib.Die(e)

    # Change the profile to the selected.
    logging.info("Selecting profile: %s for %s", profile.directory, board.root)

    try:
        ChooseProfile(board, profile)
    except MakeProfileIsNotLinkError as e:
        cros_build_lib.Die(e)
