# -*- coding: utf-8 -*-
# Copyright (c) 2010 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.

"""Manage projects in the local manifest."""

from __future__ import print_function

import platform
import os
import xml.etree.ElementTree as ElementTree

from chromite.lib import commandline
from chromite.lib import cros_build_lib
from chromite.lib import git
from chromite.lib import osutils
from chromite.lib import repo_manifest


class LocalManifest(object):
  """Class which provides an abstraction for manipulating the local manifest."""

  @classmethod
  def FromPath(cls, path, empty_if_missing=False):
    if os.path.isfile(path):
      return cls(osutils.ReadFile(path))
    elif empty_if_missing:
      cros_build_lib.Die('Manifest file, %r, not found' % path)
    return cls()

  def __init__(self, text=None):
    self._text = text or '<manifest>\n</manifest>'
    self.nodes = ElementTree.fromstring(self._text)

  def AddNonWorkonProject(self, name, path, remote=None, revision=None):
    """Add a new nonworkon project element to the manifest tree."""
    element = ElementTree.Element('project', name=name, path=path,
                                  remote=remote)
    element.attrib['workon'] = 'False'
    if revision is not None:
      element.attrib['revision'] = revision
    self.nodes.append(element)
    return element

  def GetProject(self, name, path=None):
    """Accessor method for getting a project node from the manifest tree.

    Returns:
      project element node from ElementTree, otherwise, None
    """
    if path is None:
      # Use a unique value that can't ever match.
      path = object()
    for project in self.nodes.findall('project'):
      if project.attrib['name'] == name or project.attrib['path'] == path:
        return project
    return None

  def ToString(self):
    # Reset the tail for each node, then just do a hacky replace.
    project = None
    for project in self.nodes.findall('project'):
      project.tail = '\n  '
    if project is not None:
      # Tweak the last project to not have the trailing space.
      project.tail = '\n'
    # Fix manifest tag text and tail.
    self.nodes.text = '\n  '
    self.nodes.tail = '\n'
    return ElementTree.tostring(
        self.nodes, encoding=repo_manifest.TOSTRING_ENCODING)

  def GetProjects(self):
    return list(self.nodes.findall('project'))


def _AddProjectsToManifestGroups(options, new_group):
  """Enable the given manifest groups for the configured repository."""

  groups_to_enable = ['name:%s' % x for x in new_group]

  git_config = options.git_config

  cmd = ['config', '-f', git_config, '--get', 'manifest.groups']
  enabled_groups = git.RunGit('.', cmd, check=False).output.split(',')

  # Note that ordering actually matters, thus why the following code
  # is written this way.
  # Per repo behaviour, enforce an appropriate platform group if
  # we're converting from a default manifest group to a limited one.
  # Finally, note we reprocess the existing groups; this is to allow
  # us to cleanup any user screwups, or our own screwups.
  requested_groups = (
      ['minilayout', 'platform-%s' % (platform.system().lower(),)] +
      enabled_groups + list(groups_to_enable))

  processed_groups = set()
  finalized_groups = []

  for group in requested_groups:
    if group not in processed_groups:
      finalized_groups.append(group)
      processed_groups.add(group)

  cmd = ['config', '-f', git_config, 'manifest.groups',
         ','.join(finalized_groups)]
  git.RunGit('.', cmd)


def _AssertNotMiniLayout():
  cros_build_lib.Die(
      'Your repository checkout is using the old minilayout.xml workflow; '
      'Autoupdate is no longer supported, reinstall your tree.')


def GetParser():
  """Return a command line parser."""
  parser = commandline.ArgumentParser(description=__doc__)

  # Subparsers are required by default under Python 2.  Python 3 changed to
  # not required, but didn't include a required option until 3.7.  Setting
  # the required member works in all versions (and setting dest name).
  subparsers = parser.add_subparsers(dest='command')
  subparsers.required = True

  subparser = subparsers.add_parser(
      'add',
      help='Add projects to the manifest.')
  subparser.add_argument('-w', '--workon', action='store_true',
                         default=False, help='Is this a workon package?')
  subparser.add_argument('-r', '--remote',
                         help='Remote project name (for non-workon packages).')
  subparser.add_argument('-v', '--revision',
                         help='Use to override the manifest defined default '
                              'revision used for a given project.')
  subparser.add_argument('project', help='Name of project in the manifest.')
  subparser.add_argument('path', nargs='?', help='Local path to the project.')

  return parser


def main(argv):
  parser = GetParser()
  options = parser.parse_args(argv)
  repo_dir = git.FindRepoDir(os.getcwd())
  if not repo_dir:
    parser.error('This script must be invoked from within a repository '
                 'checkout.')

  options.git_config = os.path.join(repo_dir, 'manifests.git', 'config')
  options.local_manifest_path = os.path.join(repo_dir, 'local_manifest.xml')

  manifest_sym_path = os.path.join(repo_dir, 'manifest.xml')
  if os.path.basename(os.readlink(manifest_sym_path)) == 'minilayout.xml':
    _AssertNotMiniLayout()

  # For now, we only support the add command.
  assert options.command == 'add'
  if options.workon:
    if options.path is not None:
      parser.error('Adding workon projects do not set project.')
  else:
    if options.remote is None:
      parser.error('Adding non-workon projects requires a remote.')
    if options.path is None:
      parser.error('Adding non-workon projects requires a path.')
  name = options.project
  path = options.path
  revision = options.revision
  if revision is not None:
    if (not git.IsRefsTags(revision) and
        not git.IsSHA1(revision)):
      revision = git.StripRefsHeads(revision, False)

  main_manifest = git.ManifestCheckout(os.getcwd())
  main_element = main_manifest.FindCheckouts(name)
  if path is not None:
    main_element_from_path = main_manifest.FindCheckoutFromPath(
        path, strict=False)
    if main_element_from_path is not None:
      main_element.append(main_element_from_path)

  local_manifest = LocalManifest.FromPath(options.local_manifest_path)

  if options.workon:
    if not main_element:
      parser.error('No project named %r in the default manifest.' % name)
    _AddProjectsToManifestGroups(
        options, [checkout['name'] for checkout in main_element])

  elif main_element:
    if options.remote is not None:
      # Likely this project wasn't meant to be remote, so workon main element
      print('Project already exists in manifest. Using that as workon project.')
      _AddProjectsToManifestGroups(
          options, [checkout['name'] for checkout in main_element])
    else:
      # Conflict will occur; complain.
      parser.error('Requested project name=%r path=%r will conflict with '
                   'your current manifest %s' % (
                       name, path, main_manifest.manifest_path))

  elif local_manifest.GetProject(name, path=path) is not None:
    parser.error('Requested project name=%r path=%r conflicts with '
                 'your local_manifest.xml' % (name, path))

  else:
    element = local_manifest.AddNonWorkonProject(name=name, path=path,
                                                 remote=options.remote,
                                                 revision=revision)
    _AddProjectsToManifestGroups(options, [element.attrib['name']])

    with open(options.local_manifest_path, 'w') as f:
      f.write(local_manifest.ToString())
  return 0
