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

"""A type used to represent a toolchain and its setting overrides."""

import collections
import copy
import json
import os

from chromite.lib import osutils


_ToolchainTuple = collections.namedtuple(
    "_ToolchainTuple", ("target", "setting_overrides")
)


_DEFAULT_TOOLCHAIN_KEY = "default"


class MismatchedToolchainConfigsError(Exception):
    """We have no defined resolution for conflicting toolchain configs."""


class ToolchainList:
    """Represents a list of toolchains."""

    def __init__(self, overlays) -> None:
        """Construct an instance.

        Args:
            overlays: list of overlay directories to add toolchains from.
        """
        if overlays is None:
            raise ValueError("Must specify overlays.")

        self._toolchains = []
        self._auto_default_toolchain = None
        for overlay_path in overlays:
            self._AddToolchainsFromOverlayDir(overlay_path)

    def _AddToolchainsFromOverlayDir(self, overlay_dir) -> None:
        """Add toolchains to |self| from the given overlay.

        Does not include overlays that this overlay depends on.

        Args:
            overlay_dir: absolute path to an overlay directory.
        """
        config_path = os.path.join(overlay_dir, "toolchain.conf")
        if not os.path.exists(config_path):
            # Not all overlays define toolchains.
            return

        first_target = True
        default_target = None

        config_lines = osutils.ReadFile(config_path).splitlines()
        for line in config_lines:
            # Split by hash sign so that comments are ignored.
            # Then split the line to get the tuple and its options.
            line_pieces = line.split("#", 1)[0].split(None, 1)
            if not line_pieces:
                continue
            target = line_pieces[0]
            settings = (
                json.loads(line_pieces[1]) if len(line_pieces) > 1 else {}
            )

            if first_target:
                if settings.get("default", True):
                    default_target = target
                first_target = False

            self._AddToolchain(target, setting_overrides=settings)

        if default_target:
            self._auto_default_toolchain = default_target

    def _AddToolchain(self, target, setting_overrides=None) -> None:
        """Add a toolchain to |self|.

        Args:
            target: string target (e.g. 'x86_64-cros-linux-gnu').
            setting_overrides: dictionary of setting overrides for this
                toolchain.
        """
        if setting_overrides is None:
            setting_overrides = {}
        self._toolchains.append(
            _ToolchainTuple(target=target, setting_overrides=setting_overrides)
        )

    def GetMergedToolchainSettings(self):
        """Returns a dictionary of merged toolchain settings."""
        targets = {}
        toolchains = copy.deepcopy(self._toolchains)
        if not toolchains:
            return targets

        have_default = any(
            setting_overrides.get(_DEFAULT_TOOLCHAIN_KEY, False)
            for target, setting_overrides in toolchains
        )
        if not have_default:
            assert self._auto_default_toolchain, "No toolchains!?"
            default_toolchain = _ToolchainTuple(
                self._auto_default_toolchain, {_DEFAULT_TOOLCHAIN_KEY: True}
            )
            toolchains.insert(0, default_toolchain)

        # We might get toolchain setting overrides from a couple different
        # overlays. Merge all these overrides together, disallowing conflicts.
        for toolchain in toolchains:
            targets.setdefault(toolchain.target, {})
            existing_overrides = targets[toolchain.target]
            for key, value in toolchain.setting_overrides.items():
                if (
                    key in existing_overrides
                    and existing_overrides[key] != value
                ):
                    raise MismatchedToolchainConfigsError(
                        "For toolchain %s, found %s to be set to both %r and "
                        "%r."
                        % (
                            toolchain.target,
                            key,
                            existing_overrides[key],
                            value,
                        )
                    )
                existing_overrides[key] = value

        # Now that we've merged all the setting overrides, apply them to
        # defaults.
        # TODO(b/236161656): Fix.
        # pylint: disable-next=consider-using-dict-items
        for target in targets.keys():
            settings = {
                "sdk": True,
                "crossdev": "",
                "default": False,
                "have-binpkg": True,
            }
            settings.update(targets[target])
            targets[target] = settings
        return targets
