# 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'}

_PROJECT_JSON = 'project.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
    project_json = os.path.join(project_dir, _PROJECT_JSON)

    if not os.path.exists(project_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(project_json))
    else:
      raise ProjectAlreadyExists(self.project_dir)

  def _LayoutConfPath(self):
    """Returns the path to the layout.conf file."""
    return os.path.join(self.project_dir, '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
    """
    osutils.WriteFile(
        os.path.join(self.project_dir, '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, _PROJECT_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 _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)
