# 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.

"""Utilities to work with blueprints."""

from __future__ import print_function

import os

from chromite.lib import brick_lib
from chromite.lib import workspace_lib


# Field names for specifying initial configuration.
BRICKS_FIELD = 'bricks'
BSP_FIELD = 'bsp'


class BlueprintNotFoundError(Exception):
  """The blueprint does not exist."""


class BlueprintCreationError(Exception):
  """Blueprint creation failed."""


# TODO(dpursell): Enable this shorthand blueprint specifications for all CLI
# tools. http://brbug.com/931.
def ExpandBlueprintPath(path):
  """Expand a blueprint path using some common assumptions.

  Makes the following changes to |path|:
    1. Put non-paths in //blueprints (e.g. foo -> //blueprints/foo).
    2. Add .json if no extension was given.

  Args:
    path: blueprint path.

  Returns:
    Modified blueprint path.
  """
  # Non-path arguments should be put in //blueprints by default.
  if '/' not in path:
    path = os.path.join('//blueprints', path)
  if os.path.splitext(path)[1] != '.json':
    path += '.json'
  return path


class Blueprint(object):
  """Encapsulates the interaction with a blueprint."""

  def __init__(self, blueprint_loc, initial_config=None):
    """Instantiates a blueprint object.

    Args:
      blueprint_loc: blueprint locator.  This can be a relative path to CWD, an
        absolute path, or a relative path to the root of the workspace prefixed
        with '//'.
      initial_config: A dictionary of key-value pairs to seed a new blueprint
        with if the specified blueprint doesn't already exist.

    Raises:
      BlueprintNotFoundError: No blueprint exists at |blueprint_loc| and no
        |initial_config| was given to create a new one.
      BlueprintCreationError: |initial_config| was specified but a file
        already exists at |blueprint_loc|.
    """
    self._path = (workspace_lib.LocatorToPath(blueprint_loc)
                  if workspace_lib.IsLocator(blueprint_loc) else blueprint_loc)
    self._locator = workspace_lib.PathToLocator(self._path)

    if initial_config is not None:
      self._CreateBlueprintConfig(initial_config)

    try:
      self.config = workspace_lib.ReadConfigFile(self._path)
    except IOError:
      raise BlueprintNotFoundError('Blueprint %s not found.' % self._path)

  def _CreateBlueprintConfig(self, config):
    """Create an initial blueprint config file.

    Converts all brick paths in |config| into locators then saves the
    configuration file to |self._path|.

    Currently fails if |self._path| already exists, but could be
    generalized to allow re-writing config files if needed.

    Args:
      config: configuration dictionary.

    Raises:
      BlueprintCreationError: A brick in |config| doesn't exist or an
        error occurred while saving the config file.
    """
    if os.path.exists(self._path):
      raise BlueprintCreationError('File already exists at %s.' % self._path)

    try:
      # Turn brick specifications into locators.
      if config.get(BRICKS_FIELD):
        config[BRICKS_FIELD] = [brick_lib.Brick(b).brick_locator
                                for b in config[BRICKS_FIELD]]
      if config.get(BSP_FIELD):
        config[BSP_FIELD] = brick_lib.Brick(config[BSP_FIELD]).brick_locator

      # Create the config file.
      workspace_lib.WriteConfigFile(self._path, config)
    except (brick_lib.BrickNotFound, workspace_lib.ConfigFileError) as e:
      raise BlueprintCreationError('Blueprint creation failed. %s' % e)

  def GetBricks(self):
    """Returns the bricks field of a blueprint."""
    return self.config.get(BRICKS_FIELD, [])

  def GetBSP(self):
    """Returns the BSP field of a blueprint."""
    return self.config.get(BSP_FIELD)

  def FriendlyName(self):
    """Returns the friendly name for this blueprint."""
    return workspace_lib.LocatorToFriendlyName(self._locator)

  def GetUsedBricks(self):
    """Returns the set of bricks used by this blueprint."""
    brick_map = {}
    for top_brick in self.GetBricks() + [self.GetBSP()]:
      for b in brick_lib.Brick(top_brick).BrickStack():
        brick_map[b.brick_locator] = b

    return brick_map.values()
