# -*- coding:utf-8 -*-
#
# 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 XmlManifest

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):
    for project in diff['added']:
      self.printText("A %s %s" % (project.relpath, project.revisionExpr))
      self.out.nl()

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

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

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

  def _printDiff(self, diff, color=True, pretty_format=None):
    if diff['added']:
      self.out.nl()
      self.printText('added projects : \n')
      self.out.nl()
      for project in diff['added']:
        self.printProject('\t%s' % (project.relpath))
        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' % (project.relpath))
        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' % (project.relpath))
        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 ' % (project.relpath))
        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')

  def Execute(self, opt, args):
    self.out = _Coloring(self.manifest.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 = XmlManifest(self.manifest.repodir)
    manifest1.Override(args[0], load_local_manifests=False)
    if len(args) == 1:
      manifest2 = self.manifest
    else:
      manifest2 = XmlManifest(self.manifest.repodir)
      manifest2.Override(args[1], load_local_manifests=False)

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