# Copyright 2015 The Chromium OS Authors. All rights reserved.
# 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."""

from __future__ import print_function

import copy
import collections
import json
import os

from chromite.lib import osutils


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


_DEFAULT_TOOLCHAIN_KEY = 'default'


class NoDefaultToolchainDefinedError(Exception):
  """Brillo brick stacks are required to define a default toolchain."""


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


class ToolchainList(object):
  """Represents a list of toolchains."""

  def __init__(self, brick=None, overlays=None):
    """Construct an instance.

    Args:
      brick: brick_lib.Brick object.  We'll add the toolchains used by the brick
          and its dependencies to |self|.
      overlays: list of overlay directories to add toolchains from.
    """
    if brick is None and overlays is None:
      raise ValueError('Must specify either brick or overlays.')
    if brick is not None and overlays is not None:
      raise ValueError('Must specify one of brick or overlays.')

    self._toolchains = []
    self._require_explicit_default_toolchain = True
    if brick:
      for each_brick in brick.BrickStack():
        self._AddToolchainsFromBrick(each_brick)
    else:
      self._require_explicit_default_toolchain = False
      for overlay_path in overlays:
        self._AddToolchainsFromOverlayDir(overlay_path)

  def _AddToolchainsFromOverlayDir(self, overlay_dir):
    """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

    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 {}
      self._AddToolchain(target, setting_overrides=settings)

  def _AddToolchainsFromBrick(self, brick):
    """Add toolchains to |self| defined by the given brick.

    Args:
      brick: brick_lib.Brick object.
    """
    for target, settings in brick.config.get('toolchains', {}):
      self._AddToolchain(target, setting_overrides=settings)

  def _AddToolchain(self, target, setting_overrides=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 = dict()
    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:
      if self._require_explicit_default_toolchain:
        raise NoDefaultToolchainDefinedError(
            'Expected to find a toolchain marked as default.')
      default_toolchain = _ToolchainTuple(toolchains[0].target,
                                          {_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, dict())
      existing_overrides = targets[toolchain.target]
      for key, value in toolchain.setting_overrides.iteritems():
        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.
    for target in targets.iterkeys():
      settings = {
          'sdk': True,
          'crossdev': '',
          'default': False,
      }
      settings.update(targets[target])
      targets[target] = settings
    return targets
