# -*- 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 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):
    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, pretty_format=pretty_format)

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

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