# -*- coding: utf-8 -*-
# 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 MismatchedToolchainConfigsError(Exception):
  """We have no defined resolution for conflicting toolchain configs."""


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

  def __init__(self, overlays):
    """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):
    """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):
    """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:
      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, dict())
      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.
    for target in targets.keys():
      settings = {
          'sdk': True,
          'crossdev': '',
          'default': False,
      }
      settings.update(targets[target])
      targets[target] = settings
    return targets
