# Copyright (C) 2014 The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

from color import Coloring
from command import PagedCommand
from manifest_xml import RepoClient


class _Coloring(Coloring):
  def __init__(self, config):
    Coloring.__init__(self, config, "status")


class Diffmanifests(PagedCommand):
  """ A command to see logs in projects represented by manifests

  This is used to see deeper differences between manifests. Where a simple
  diff would only show a diff of sha1s for example, this command will display
  the logs of the project between both sha1s, allowing user to see diff at a
  deeper level.
  """

  COMMON = True
  helpSummary = "Manifest diff utility"
  helpUsage = """%prog manifest1.xml [manifest2.xml] [options]"""

  helpDescription = """
The %prog command shows differences between project revisions of manifest1 and
manifest2. if manifest2 is not specified, current manifest.xml will be used
instead. Both absolute and relative paths may be used for manifests. Relative
paths start from project's ".repo/manifests" folder.

The --raw option Displays the diff in a way that facilitates parsing, the
project pattern will be <status> <path> <revision from> [<revision to>] and the
commit pattern will be <status> <onelined log> with status values respectively :

  A = Added project
  R = Removed project
  C = Changed project
  U = Project with unreachable revision(s) (revision(s) not found)

for project, and

   A = Added commit
   R = Removed commit

for a commit.

Only changed projects may contain commits, and commit status always starts with
a space, and are part of last printed project.
Unreachable revisions may occur if project is not up to date or if repo has not
been initialized with all the groups, in which case some projects won't be
synced and their revisions won't be found.

"""

  def _Options(self, p):
    p.add_option('--raw',
                 dest='raw', action='store_true',
                 help='display raw diff')
    p.add_option('--no-color',
                 dest='color', action='store_false', default=True,
                 help='does not display the diff in color')
    p.add_option('--pretty-format',
                 dest='pretty_format', action='store',
                 metavar='<FORMAT>',
                 help='print the log using a custom git pretty format string')

  def _printRawDiff(self, diff, pretty_format=None, local=False):
    _RelPath = lambda p: p.RelPath(local=local)
    for project in diff['added']:
      self.printText("A %s %s" % (_RelPath(project), project.revisionExpr))
      self.out.nl()

    for project in diff['removed']:
      self.printText("R %s %s" % (_RelPath(project), project.revisionExpr))
      self.out.nl()

    for project, otherProject in diff['changed']:
      self.printText("C %s %s %s" % (_RelPath(project), project.revisionExpr,
                                     otherProject.revisionExpr))
      self.out.nl()
      self._printLogs(project, otherProject, raw=True, color=False, pretty_format=pretty_format)

    for project, otherProject in diff['unreachable']:
      self.printText("U %s %s %s" % (_RelPath(project), project.revisionExpr,
                                     otherProject.revisionExpr))
      self.out.nl()

  def _printDiff(self, diff, color=True, pretty_format=None, local=False):
    _RelPath = lambda p: p.RelPath(local=local)
    if diff['added']:
      self.out.nl()
      self.printText('added projects : \n')
      self.out.nl()
      for project in diff['added']:
        self.printProject('\t%s' % (_RelPath(project)))
        self.printText(' at revision ')
        self.printRevision(project.revisionExpr)
        self.out.nl()

    if diff['removed']:
      self.out.nl()
      self.printText('removed projects : \n')
      self.out.nl()
      for project in diff['removed']:
        self.printProject('\t%s' % (_RelPath(project)))
        self.printText(' at revision ')
        self.printRevision(project.revisionExpr)
        self.out.nl()

    if diff['missing']:
      self.out.nl()
      self.printText('missing projects : \n')
      self.out.nl()
      for project in diff['missing']:
        self.printProject('\t%s' % (_RelPath(project)))
        self.printText(' at revision ')
        self.printRevision(project.revisionExpr)
        self.out.nl()

    if diff['changed']:
      self.out.nl()
      self.printText('changed projects : \n')
      self.out.nl()
      for project, otherProject in diff['changed']:
        self.printProject('\t%s' % (_RelPath(project)))
        self.printText(' changed from ')
        self.printRevision(project.revisionExpr)
        self.printText(' to ')
        self.printRevision(otherProject.revisionExpr)
        self.out.nl()
        self._printLogs(project, otherProject, raw=False, color=color,
                        pretty_format=pretty_format)
        self.out.nl()

    if diff['unreachable']:
      self.out.nl()
      self.printText('projects with unreachable revisions : \n')
      self.out.nl()
      for project, otherProject in diff['unreachable']:
        self.printProject('\t%s ' % (_RelPath(project)))
        self.printRevision(project.revisionExpr)
        self.printText(' or ')
        self.printRevision(otherProject.revisionExpr)
        self.printText(' not found')
        self.out.nl()

  def _printLogs(self, project, otherProject, raw=False, color=True,
                 pretty_format=None):

    logs = project.getAddedAndRemovedLogs(otherProject,
                                          oneline=(pretty_format is None),
                                          color=color,
                                          pretty_format=pretty_format)
    if logs['removed']:
      removedLogs = logs['removed'].split('\n')
      for log in removedLogs:
        if log.strip():
          if raw:
            self.printText(' R ' + log)
            self.out.nl()
          else:
            self.printRemoved('\t\t[-] ')
            self.printText(log)
            self.out.nl()

    if logs['added']:
      addedLogs = logs['added'].split('\n')
      for log in addedLogs:
        if log.strip():
          if raw:
            self.printText(' A ' + log)
            self.out.nl()
          else:
            self.printAdded('\t\t[+] ')
            self.printText(log)
            self.out.nl()

  def ValidateOptions(self, opt, args):
    if not args or len(args) > 2:
      self.OptionParser.error('missing manifests to diff')
    if opt.this_manifest_only is False:
      raise self.OptionParser.error(
          '`diffmanifest` only supports the current tree')

  def Execute(self, opt, args):
    self.out = _Coloring(self.client.globalConfig)
    self.printText = self.out.nofmt_printer('text')
    if opt.color:
      self.printProject = self.out.nofmt_printer('project', attr='bold')
      self.printAdded = self.out.nofmt_printer('green', fg='green', attr='bold')
      self.printRemoved = self.out.nofmt_printer('red', fg='red', attr='bold')
      self.printRevision = self.out.nofmt_printer('revision', fg='yellow')
    else:
      self.printProject = self.printAdded = self.printRemoved = self.printRevision = self.printText

    manifest1 = RepoClient(self.repodir)
    manifest1.Override(args[0], load_local_manifests=False)
    if len(args) == 1:
      manifest2 = self.manifest
    else:
      manifest2 = RepoClient(self.repodir)
      manifest2.Override(args[1], load_local_manifests=False)

    diff = manifest1.projectsDiff(manifest2)
    if opt.raw:
      self._printRawDiff(diff, pretty_format=opt.pretty_format,
                         local=opt.this_manifest_only)
    else:
      self._printDiff(diff, color=opt.color, pretty_format=opt.pretty_format,
                      local=opt.this_manifest_only)
