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

"""Common project related utilities."""

from __future__ import print_function

import json
import os

from chromite.lib import cros_build_lib
from chromite.lib import osutils
from chromite.lib import portage_util

_DEFAULT_LAYOUT_CONF = {'profile-formats': 'portage-2',
                        'thin-manifests': 'true',
                        'use-manifests': 'true'}

_CONFIG_JSON = 'config.json'


class ProjectAlreadyExists(Exception):
  """The project already exists."""


class ProjectNotFound(Exception):
  """The project does not exist."""

class ProjectFeatureNotSupported(Exception):
  """Attempted feature not supported for this project."""

class Project(object):
  """Encapsulates the interaction with a project."""

  def __init__(self, project_dir, initial_config=None, allow_legacy=True):
    """Instantiates a project object.

    Args:
      project_dir: The root directory of the project.
      initial_config: The initial configuration as a python dictionary.
        If not None, creates a project with this configuration.
      allow_legacy: Allow board overlays, simulating a basic read-only config.
        Ignored if |initial_config| is not None.

    Raises:
      ProjectNotFound: when |project_dir| is not a project and no initial
        configuration was provided.
      ProjectAlreadyExists: when trying to create a project but |project_dir|
        already contains one.
    """
    self.project_dir = project_dir
    self.config = None
    self.legacy = False
    config_json = os.path.join(project_dir, _CONFIG_JSON)

    if not os.path.exists(config_json):
      if initial_config:
        self.UpdateConfig(initial_config)
      elif allow_legacy:
        self.legacy = True
        try:
          self.config = {'name': self._ReadLayoutConf()['repo-name']}
        except (IOError, KeyError):
          pass

      if self.config is None:
        raise ProjectNotFound(self.project_dir)
    elif initial_config is None:
      self.config = json.loads(osutils.ReadFile(config_json))
    else:
      raise ProjectAlreadyExists(self.project_dir)

  def _LayoutConfPath(self):
    """Returns the path to the layout.conf file."""
    if self.legacy:
      return os.path.join(self.project_dir, 'metadata', 'layout.conf')
    return os.path.join(self.project_dir, 'packages', 'metadata', 'layout.conf')

  def _WriteLayoutConf(self, content):
    """Writes layout.conf.

    Sets unset fields to a sensible default and write |content| in layout.conf
    in the right format.

    Args:
      content: dictionary containing the set fields in layout.conf.
    """
    for k, v in _DEFAULT_LAYOUT_CONF.iteritems():
      content.setdefault(k, v)

    content_str = ''.join(['%s = %s\n' % (k, v)
                           for k, v in content.iteritems()])
    osutils.WriteFile(self._LayoutConfPath(), content_str, makedirs=True)

  def _ReadLayoutConf(self):
    """Returns the content of layout.conf as a Python dictionary."""
    def ParseConfLine(line):
      k, _, v = line.partition('=')
      return k.strip(), v.strip() or None

    content_str = osutils.ReadFile(self._LayoutConfPath())
    return dict(ParseConfLine(line) for line in content_str.splitlines())

  def _WriteParents(self, parents):
    """Writes the parents profile.

    Args:
      parents: list of overlay names
    """
    if self.legacy:
      raise ProjectFeatureNotSupported()

    osutils.WriteFile(os.path.join(self.project_dir, 'packages', 'profiles',
                                   'base', 'parent'),
                      ''.join([p + '\n' for p in parents]), makedirs=True)

  def UpdateConfig(self, config, regenerate=True):
    """Updates the project's configuration.

    Write the json representation of |config| in project.json.
    If |regenerate| is true, regenerate the portage configuration files in
    this project to match the new project.json.

    Args:
      config: project configuration as a python dict
      regenerate: if True, regenerate autogenerated project files
    """
    if self.legacy:
      raise ProjectFeatureNotSupported(
          'Cannot update configuration of legacy project %s' % self.project_dir)

    self.config = config
    formatted_config = json.dumps(config, sort_keys=True, indent=4,
                                  separators=(',', ': '))
    osutils.WriteFile(os.path.join(self.project_dir, _CONFIG_JSON),
                      formatted_config, makedirs=True)

    if regenerate:
      self.GeneratePortageConfig()

  def GeneratePortageConfig(self):
    """Generates all autogenerated project files."""
    # We don't generate anything in legacy project so everything is up-to-date.
    if self.legacy:
      return

    deps = [d.get('name', None) for d in self.config.get('dependencies', [])]
    if None in deps:
      cros_build_lib.Die('Invalid dependency name')

    self._WriteLayoutConf(
        {'masters': ' '.join(['portage-stable', 'chromiumos'] + deps),
         'repo-name': self.config['name']})

    self._WriteParents([m + ':base' for m in deps])

  def Inherits(self, project_name):
    """Checks whether this project contains |project_name|.

    Args:
      project_name: The name of the project to check containment.

    Returns:
      Whether |project_name| is contained in this project.
    """
    return bool('name' in self.config and
                _FindProjectInOverlays(project_name, self.config['name']))

  def MainPackages(self):
    """Returns the project's main package(s).

    This finds the 'main_package' property.  It nevertheless returns a (single
    element) list as it is easier to work with.

    Returns:
      A list of main packages; empty if no main package configured.
    """
    main_package = self.config.get('main_package')
    return [main_package] if main_package else []

  def OverlayDir(self):
    """Returns the project's overlay directory."""
    return os.path.join(self.project_dir, 'packages')


def _FindProjectInOverlays(name, base=None):
  """Returns the parent project of |base| that matches |name|.

  Will prefer an exact match, but if one does not exist then it would settle
  for the private repo name. This is needed for backward compatibility with
  Chrome OS repo naming convention and should be adapted accordingly.

  Args:
    name: Overlay/project name to look for.
    base: Base project/overlay name to scan from; if None, uses |name|.

  Returns:
    The project associated to |name| if one exists, otherwise None.
  """
  if not name:
    return None
  if base is None:
    base = name

  private_proj = None
  try:
    for overlay in portage_util.FindOverlays('both', base):
      try:
        proj = Project(overlay)
        proj_name = proj.config.get('name')
        if proj_name == name:
          return proj
        if proj_name.rstrip('-private') == name:
          private_proj = proj
      except ProjectNotFound:
        pass
  except portage_util.MissingOverlayException:
    pass

  return private_proj


def FindProjectInPath(path=None):
  """Returns the root directory of the project containing a path.

  Return the first parent directory of |path| that is the root of a project.
  This method is used for project auto-detection and does not consider legacy.

  Args:
    path: path to a directory. If |path| is None, |path| will be set to CWD.

  Returns:
    The path to the first parent that is a project directory if one exist.
    Otherwise return None.
  """
  for p in osutils.IteratePathParents(path or os.getcwd()):
    try:
      return Project(p, allow_legacy=False)
    except ProjectNotFound:
      pass

  return None


def FindProjectByName(name):
  """Returns the project associated to |name|.

  Args:
    name: A project name.

  Returns:
    The project associated to |name| if one exists, otherwise None.
  """
  return _FindProjectInOverlays(name)
