# Copyright 2008 Google Inc.
#
# 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.

"""Diff rendering in HTML for Gerrit."""

# Python imports
import re
import cgi
import difflib
import logging
import urlparse

# AppEngine imports
from google.appengine.api import urlfetch
from google.appengine.api import users
from google.appengine.ext import db

# Django imports
from django.template import loader

# Local imports
import library
import models
import patching
import intra_region_diff


# NOTE: this function is duplicated in upload.py, keep them in sync.
def SplitPatch(data):
  """Splits a patch into separate pieces for each file.

  Args:
    data: A string containing the output of svn diff.

  Returns:
    A list of 2-tuple (filename, text) where text is the svn diff output
      pertaining to filename.
  """
  patches = []
  filename = None
  diff = []
  for line in data.splitlines(True):
    new_filename = None
    if line.startswith('Index:'):
      unused, new_filename = line.split(':', 1)
      new_filename = new_filename.strip()
    elif line.startswith('Property changes on:'):
      unused, temp_filename = line.split(':', 1)
      # When a file is modified, paths use '/' between directories, however
      # when a property is modified '\' is used on Windows.  Make them the same
      # otherwise the file shows up twice.
      temp_filename = temp_filename.strip().replace('\\', '/')
      if temp_filename != filename:
        # File has property changes but no modifications, create a new diff.
        new_filename = temp_filename
    if new_filename:
      if filename and diff:
        patches.append((filename, ''.join(diff)))
      filename = new_filename
      diff = [line]
      continue
    if diff is not None:
      diff.append(line)
  if filename and diff:
    patches.append((filename, ''.join(diff)))
  return patches



def RenderDiffTableRows(request, old_lines, chunks, patch,
                        colwidth=80,
                        debug=False,
                        context=models.DEFAULT_CONTEXT):
  """Render the HTML table rows for a side-by-side diff for a patch.

  Args:
    request: Django Request object.
    old_lines: List of lines representing the original file.
    chunks: List of chunks as returned by patching.ParsePatchToChunks().
    patch: A models.Patch instance.
    colwidth: Optional column width (default 80).
    debug: Optional debugging flag (default False).
    context: Maximum number of rows surrounding a change (default CONTEXT).

  Yields:
    Strings, each of which represents the text rendering one complete
    pair of lines of the side-by-side diff, possibly including comments.
    Each yielded string may consist of several <tr> elements.
  """
  rows =  _RenderDiffTableRows(request, old_lines, chunks, patch,
                               colwidth, debug)
  return _CleanupTableRowsGenerator(rows, context)


def RenderDiff2TableRows(request, old_lines, old_patch, new_lines, new_patch,
                         colwidth=80,
                         debug=False,
                         context=models.DEFAULT_CONTEXT):
  """Render the HTML table rows for a side-by-side diff between two patches.

  Args:
    request: Django Request object.
    old_lines: List of lines representing the patched file on the left.
    old_patch: The models.Patch instance corresponding to old_lines.
    new_lines: List of lines representing the patched file on the right.
    new_patch: The models.Patch instance corresponding to new_lines.
    colwidth: Optional column width (default 80).
    debug: Optional debugging flag (default False).
    context: Maximum number of visible context lines (default models.DEFAULT_CONTEXT).

  Yields:
    Strings, each of which represents the text rendering one complete
    pair of lines of the side-by-side diff, possibly including comments.
    Each yielded string may consist of several <tr> elements.
  """
  rows = _RenderDiff2TableRows(request, old_lines, old_patch,
                               new_lines, new_patch, colwidth, debug)
  return _CleanupTableRowsGenerator(rows, context)


def _CleanupTableRowsGenerator(rows, context):
  """Cleanup rows returned by _TableRowGenerator for output.

  Args:
    rows: List of tuples (tag, text)
    context: Maximum number of visible context lines.

  Yields:
    Rows marked as 'equal' are possibly contracted using _ShortenBuffer().
    Stops on rows marked as 'error'.
  """
  buffer = []
  for tag, text in rows:
    if tag == 'equal':
      buffer.append(text)
      continue
    else:
      for t in _ShortenBuffer(buffer, context):
        yield t
      buffer = []
    yield text
    if tag == 'error':
      yield None
      break
  if buffer:
    for t in _ShortenBuffer(buffer, context):
      yield t


def _ShortenBuffer(buffer, context):
  """Render a possibly contracted series of HTML table rows.

  Args:
    buffer: a list of strings representing HTML table rows.
    context: Maximum number of visible context lines.

  Yields:
    If the buffer has fewer than 3 times context items, yield all
    the items.  Otherwise, yield the first context items, a single
    table row representing the contraction, and the last context
    items.
  """
  if len(buffer) < 3*context:
    for t in buffer:
      yield t
  else:
    last_id = None
    for t in buffer[:context]:
      m = re.match('^<tr( name="hook")? id="pair-(?P<rowcount>\d+)">', t)
      if m:
        last_id = int(m.groupdict().get("rowcount"))
      yield t
    skip = len(buffer) - 2*context
    if skip <= 10:
      expand_link = ('<a href="javascript:M_expandSkipped(%(before)d, '
                     '%(after)d, \'b\', %(skip)d)">Show</a>')
    else:
      expand_link = ('<a href="javascript:M_expandSkipped(%(before)d, '
                     '%(after)d, \'t\', %(skip)d)">Show 10 above</a> '
                     '<a href="javascript:M_expandSkipped(%(before)d, '
                     '%(after)d, \'b\', %(skip)d)">Show 10 below</a> ')
    expand_link = expand_link % {'before': last_id+1,
                                 'after': last_id+skip,
                                 'skip': last_id}
    yield ('<tr id="skip-%d"><td colspan="2" align="center" '
           'style="background:lightblue">'
           '(...skipping <span id="skipcount-%d">%d</span> matching lines...) '
           '<span id="skiplinks-%d">%s</span>'
           '</td></tr>\n' % (last_id, last_id, skip,
                             last_id, expand_link))
    for t in buffer[-context:]:
      yield t


def _RenderDiff2TableRows(request, old_lines, old_patch, new_lines, new_patch,
                         colwidth=80, debug=False):
  """Internal version of RenderDiff2TableRows().

  Args:
    The same as for RenderDiff2TableRows.

  Yields:
    Tuples (tag, row) where tag is an indication of the row type.
  """
  old_dict = {}
  new_dict = {}
  for patch, dct in [(old_patch, old_dict), (new_patch, new_dict)]:
    # XXX GQL doesn't support OR yet...  Otherwise we'd be using that.
    for comment in models.Comment.gql(
        'WHERE patch = :1 AND left = FALSE ORDER BY date', patch):
      if comment.draft and comment.author != request.user:
        continue  # Only show your own drafts
      comment.complete(patch)
      lst = dct.setdefault(comment.lineno, [])
      lst.append(comment)
      library.prefetch_names([comment.author])
  return _TableRowGenerator(old_patch, old_dict, len(old_lines)+1, 'new',
                            new_patch, new_dict, len(new_lines)+1, 'new',
                            _GenerateTriples(old_lines, new_lines),
                            colwidth, debug)


def _GenerateTriples(old_lines, new_lines):
  """Helper for _RenderDiff2TableRows yielding input for _TableRowGenerator.

  Args:
    old_lines: List of lines representing the patched file on the left.
    new_lines: List of lines representing the patched file on the right.

  Yields:
    Tuples (tag, old_slice, new_slice) where tag is a tag as returned by
    difflib.SequenceMatchser.get_opcodes(), and old_slice and new_slice
    are lists of lines taken from old_lines and new_lines.
  """
  sm = difflib.SequenceMatcher(None, old_lines, new_lines)
  for tag, i1, i2, j1, j2 in sm.get_opcodes():
    yield tag, old_lines[i1:i2], new_lines[j1:j2]


def _GetComments(request):
  """Helper that returns comments for a patch.

  Args:
    request: Django Request object.

  Returns:
    A 2-tuple of (old, new) where old/new are dictionaries that holds comments
      for that file, mapping from line number to a Comment entity.
  """
  old_dict = {}
  new_dict = {}
  # XXX GQL doesn't support OR yet...  Otherwise we'd be using
  # .gql('WHERE patch = :1 AND (draft = FALSE OR author = :2) ORDER BY data',
  #      patch, request.user)
  for comment in models.Comment.gql('WHERE patch = :1 ORDER BY date',
                                    request.patch):
    if comment.draft and comment.author != request.user:
      continue  # Only show your own drafts
    comment.complete(request.patch)
    if comment.left:
      dct = old_dict
    else:
      dct = new_dict
    dct.setdefault(comment.lineno, []).append(comment)
    library.prefetch_names([comment.author])
  return old_dict, new_dict


def _RenderDiffTableRows(request, old_lines, chunks, patch,
                         colwidth=80, debug=False):
  """Internal version of RenderDiffTableRows().

  Args:
    The same as for RenderDiffTableRows.

  Yields:
    Tuples (tag, row) where tag is an indication of the row type.
  """
  old_dict = {}
  new_dict = {}
  if patch:
    old_dict, new_dict = _GetComments(request)
  old_max, new_max = _ComputeLineCounts(old_lines, chunks)
  return _TableRowGenerator(patch, old_dict, old_max, 'old',
                            patch, new_dict, new_max, 'new',
                            patching.PatchChunks(old_lines, chunks),
                            colwidth, debug)


def _TableRowGenerator(old_patch, old_dict, old_max, old_snapshot,
                       new_patch, new_dict, new_max, new_snapshot,
                       triple_iterator, colwidth=80, debug=False):
  """Helper function to render side-by-side table rows.

  Args:
    old_patch: First models.Patch instance.
    old_dict: Dictionary with line numbers as keys and comments as values (left)
    old_max: Line count of the patch on the left.
    old_snapshot: A tag used in the comments form.
    new_patch: Second models.Patch instance.
    new_dict: Same as old_dict, but for the right side.
    new_max: Line count of the patch on the right.
    new_snapshot: A tag used in the comments form.
    triple_iterator: Iterator that yields (tag, old, new) triples.
    colwidth: Optional column width (default 80).
    debug: Optional debugging flag (default False).

  Yields:
    Tuples (tag, row) where tag is an indication of the row type and
    row is an HTML fragment representing one or more <td> elements.
  """
  diff_params = intra_region_diff.GetDiffParams(dbg=debug)
  ndigits = 1 + max(len(str(old_max)), len(str(new_max)))
  indent = 1 + ndigits
  old_offset = new_offset = 0
  row_count = 0

  # Render a row with a message if a side is empty or both sides are equal.
  if old_patch == new_patch and (old_max == 0 or new_max == 0):
    if old_max == 0:
      msg_old = '(Empty)'
    else:
      msg_old = ''
    if new_max == 0:
      msg_new = '(Empty)'
    else:
      msg_new = ''
    yield '', ('<tr><td class="info">%s</td>'
               '<td class="info">%s</td></tr>' % (msg_old, msg_new))
  # TODO(sop)
  #elif old_patch == new_patch:
  #  old_patch.patch_hash == new_patch.patch_hash
  #  yield '', ('<tr><td class="info" colspan="2">'
  #             '(Both sides are equal)</td></tr>')

  for tag, old, new in triple_iterator:
    if tag.startswith('error'):
      yield 'error', '<tr><td><h3>%s</h3></td></tr>\n' % cgi.escape(tag)
      return
    old1 = old_offset
    old_offset = old2 = old1 + len(old)
    new1 = new_offset
    new_offset = new2 = new1 + len(new)
    old_buff = []
    new_buff = []
    frag_list = []
    do_ir_diff = tag == 'replace' and intra_region_diff.CanDoIRDiff(old, new)

    for i in xrange(max(len(old), len(new))):
      row_count += 1
      old_lineno = old1 + i + 1
      new_lineno = new1 + i + 1
      old_valid = old1+i < old2
      new_valid = new1+i < new2

      # Start rendering the first row
      frags = []
      if i == 0 and tag != 'equal':
        # Mark the first row of each non-equal chunk as a 'hook'.
        frags.append('<tr name="hook"')
      else:
        frags.append('<tr')
      frags.append(' id="pair-%d">' % row_count)

      old_intra_diff = ''
      new_intra_diff = ''
      if old_valid:
        old_intra_diff = old[i]
      if new_valid:
        new_intra_diff = new[i]

      frag_list.append(frags)
      if do_ir_diff:
        # Don't render yet. Keep saving state necessary to render the whole
        # region until we have encountered all the lines in the region.
        old_buff.append([old_valid, old_lineno, old_intra_diff])
        new_buff.append([new_valid, new_lineno, new_intra_diff])
      else:
        # We render line by line as usual if do_ir_diff is false
        old_intra_diff = intra_region_diff.Fold(
          old_intra_diff, colwidth + indent, indent, indent)
        new_intra_diff = intra_region_diff.Fold(
          new_intra_diff, colwidth + indent, indent, indent)
        old_buff_out = [[old_valid, old_lineno,
                         (old_intra_diff, True, None)]]
        new_buff_out = [[new_valid, new_lineno,
                         (new_intra_diff, True, None)]]
        for tg, frag in _RenderDiffInternal(old_buff_out, new_buff_out,
                                            ndigits, tag, frag_list,
                                            do_ir_diff,
                                            old_dict, new_dict,
                                            old_patch, new_patch,
                                            old_snapshot, new_snapshot,
                                            colwidth, debug):
          yield tg, frag
        frag_list = []

    if do_ir_diff:
      # So this was a replace block which means that the whole region still
      # needs to be rendered.
      old_lines = [b[2] for b in old_buff]
      new_lines = [b[2] for b in new_buff]
      ret = intra_region_diff.IntraRegionDiff(old_lines, new_lines,
                                              diff_params)
      old_chunks, new_chunks, ratio = ret
      old_tag = 'old'
      new_tag = 'new'

      old_diff_out = intra_region_diff.RenderIntraRegionDiff(
        old_lines, old_chunks, old_tag, ratio,
        limit=colwidth, indent=indent,
        dbg=debug)
      new_diff_out = intra_region_diff.RenderIntraRegionDiff(
        new_lines, new_chunks, new_tag, ratio,
        limit=colwidth, indent=indent,
        dbg=debug)
      for (i, b) in enumerate(old_buff):
        b[2] = old_diff_out[i]
      for (i, b) in enumerate(new_buff):
        b[2] = new_diff_out[i]

      for tg, frag in _RenderDiffInternal(old_buff, new_buff,
                                          ndigits, tag, frag_list,
                                          do_ir_diff,
                                          old_dict, new_dict,
                                          old_patch, new_patch,
                                          old_snapshot, new_snapshot,
                                          colwidth, debug):
        yield tg, frag
      old_buff = []
      new_buff = []


def _CleanupTableRows(rows):
  """Cleanup rows returned by _TableRowGenerator.

  Args:
    rows: Sequence of (tag, text) tuples.

  Yields:
    Rows marked as 'equal' are possibly contracted using _ShortenBuffer().
    Stops on rows marked as 'error'.
  """
  buffer = []
  for tag, text in rows:
    if tag == 'equal':
      buffer.append(text)
      continue
    else:
      for t in _ShortenBuffer(buffer):
        yield t
      buffer = []
    yield text
    if tag == 'error':
      yield None
      break
  if buffer:
    for t in _ShortenBuffer(buffer):
      yield t


def _RenderDiffInternal(old_buff, new_buff, ndigits, tag, frag_list,
                        do_ir_diff, old_dict, new_dict,
                        old_patch, new_patch,
                        old_snapshot, new_snapshot,
                        colwidth, debug):
  """Helper for _TableRowGenerator()."""
  obegin = (intra_region_diff.BEGIN_TAG %
            intra_region_diff.COLOR_SCHEME['old']['match'])
  nbegin = (intra_region_diff.BEGIN_TAG %
            intra_region_diff.COLOR_SCHEME['new']['match'])
  oend = intra_region_diff.END_TAG
  nend = oend
  user = users.get_current_user()

  for i in xrange(len(old_buff)):
    tg = tag
    old_valid, old_lineno, old_out = old_buff[i]
    new_valid, new_lineno, new_out = new_buff[i]
    old_intra_diff, old_has_newline, old_debug_info = old_out
    new_intra_diff, new_has_newline, new_debug_info = new_out

    frags = frag_list[i]
    # Render left text column
    frags.append(_RenderDiffColumn(old_patch, old_valid, tag, ndigits,
                                   old_lineno, obegin, oend, old_intra_diff,
                                   do_ir_diff, old_has_newline, 'old'))

    # Render right text column
    frags.append(_RenderDiffColumn(new_patch, new_valid, tag, ndigits,
                                   new_lineno, nbegin, nend, new_intra_diff,
                                   do_ir_diff, new_has_newline, 'new'))

    # End rendering the first row
    frags.append('</tr>\n')

    if debug:
      frags.append('<tr>')
      if old_debug_info:
        frags.append('<td class="debug-info">%s</td>' %
                     old_debug_info.replace('\n', '<br>'))
      else:
        frags.append('<td></td>')
      if new_debug_info:
        frags.append('<td class="debug-info">%s</td>' %
                     new_debug_info.replace('\n', '<br>'))
      else:
        frags.append('<td></td>')
      frags.append('</tr>\n')

    if old_patch or new_patch:
      # Start rendering the second row
      if ((old_valid and old_lineno in old_dict) or
          (new_valid and new_lineno in new_dict)):
        tg += '_comment'
        frags.append('<tr class="inline-comments" name="hook">')
      else:
        frags.append('<tr class="inline-comments">')

      # Render left inline comments
      frags.append(_RenderInlineComments(old_valid, old_lineno, old_dict,
                                         user, old_patch, old_snapshot, 'old'))

      # Render right inline comments
      frags.append(_RenderInlineComments(new_valid, new_lineno, new_dict,
                                         user, new_patch, new_snapshot, 'new'))

      # End rendering the second row
      frags.append('</tr>\n')

    # Yield the combined fragments
    yield tg, ''.join(frags)


def _RenderDiffColumn(patch, line_valid, tag, ndigits, lineno, begin, end,
                      intra_diff, do_ir_diff, has_newline, prefix):
  """Helper function for _RenderDiffInternal().

  Returns:
    A rendered column.
  """
  if line_valid:
    cls_attr = '%s%s' % (prefix, tag)
    if tag == 'equal':
      lno = '%*d' % (ndigits, lineno)
    else:
      lno = _MarkupNumber(ndigits, lineno, 'u')
    if tag == 'replace':
      col_content = ('%s%s %s%s' % (begin, lno, end, intra_diff))
      # If IR diff has been turned off or there is no matching new line at
      # the end then switch to dark background CSS style.
      if not do_ir_diff or not has_newline:
        cls_attr = cls_attr + '1'
    else:
      col_content = '%s %s' % (lno, intra_diff)
    return '<td class="%s" id="%scode%d">%s</td>' % (cls_attr, prefix,
                                                     lineno, col_content)
  else:
    return '<td class="%sblank"></td>' % prefix


def _RenderInlineComments(line_valid, lineno, data, user,
                          patch, snapshot, prefix):
  """Helper function for _RenderDiffInternal().

  Returns:
    Rendered comments.
  """
  comments = []
  if line_valid:
    comments.append('<td id="%s-line-%s">' % (prefix, lineno))
    if lineno in data:
      comments.append(
        _ExpandTemplate('inline_comment.html',
                        inline_draft_url='/inline_draft',
                        user=user,
                        patch=patch,
                        patchset=patch.patchset,
                        change=patch.patchset.change,
                        snapshot=snapshot,
                        side='a' if prefix == 'old' else 'b',
                        comments=data[lineno],
                        lineno=lineno,
                        ))
    comments.append('</td>')
  else:
    comments.append('<td></td>')
  return ''.join(comments)


def RenderUnifiedTableRows(request, parsed_lines):
  """Render the HTML table rows for a unified diff for a patch.

  Args:
    request: Django Request object.
    parsed_lines: List of tuples for each line that contain the line number,
      if they exist, for the old and new file.

  Returns:
    A list of html table rows.
  """
  old_dict, new_dict = _GetComments(request)

  rows = []
  for old_line_no, new_line_no, line_text in parsed_lines:
    row1_id = row2_id = ''
    # When a line is unchanged (i.e. both old_line_no and new_line_no aren't 0)
    # pick the old column line numbers when adding a comment.
    if old_line_no:
      row1_id = 'id="oldcode%d"' % old_line_no
      row2_id = 'id="old-line-%d"' % old_line_no
    elif new_line_no:
      row1_id = 'id="newcode%d"' % new_line_no
      row2_id = 'id="new-line-%d"' % new_line_no
    rows.append('<tr><td class="udiff" %s>%s</td></tr>' %
                (row1_id, cgi.escape(line_text)))

    frags = []
    if old_line_no in old_dict or new_line_no in new_dict:
      frags.append('<tr class="inline-comments" name="hook">')
      if old_line_no in old_dict:
        dct = old_dict
        line_no = old_line_no
        snapshot = 'old'
      else:
        dct = new_dict
        line_no = new_line_no
        snapshot = 'new'
      frags.append(_RenderInlineComments(True, line_no, dct, request.user,
                   request.patch, snapshot, snapshot))
    else:
      frags.append('<tr class="inline-comments">')
      frags.append('<td ' + row2_id +'></td>')
    frags.append('</tr>')
    rows.append(''.join(frags))
  return rows


def _ComputeLineCounts(old_lines, chunks):
  """Compute the length of the old and new sides of a diff.

  Args:
    old_lines: List of lines representing the original file.
    chunks: List of chunks as returned by patching.ParsePatchToChunks().

  Returns:
    A tuple (old_len, new_len) representing len(old_lines) and
    len(new_lines), where new_lines is the list representing the
    result of applying the patch chunks to old_lines, however, without
    actually computing new_lines.
  """
  old_len = len(old_lines)
  new_len = old_len
  if chunks:
    (old_a, old_b), (new_a, new_b), old_lines, new_lines = chunks[-1]
    new_len += new_b - old_b
  return old_len, new_len


def _MarkupNumber(ndigits, number, tag):
  """Format a number in HTML in a given width with extra markup.

  Args:
    ndigits: the total width available for formatting
    number: the number to be formatted
    tag: HTML tag name, e.g. 'u'

  Returns:
    An HTML string that displays as ndigits wide, with the
    number right-aligned and surrounded by an HTML tag; for example,
    _MarkupNumber(42, 4, 'u') returns '  <u>42</u>'.
  """
  formatted_number = str(number)
  space_prefix = ' ' * (ndigits - len(formatted_number))
  return '%s<%s>%s</%s>' % (space_prefix, tag, formatted_number, tag)


def _ExpandTemplate(name, **params):
  """Wrapper around django.template.loader.render_to_string().

  For convenience, this takes keyword arguments instead of a dict.
  """
  return loader.render_to_string(name, params)


def ToText(text):
  """Helper to turn a string into a db.Text instance.

  Args:
    text: a string.

  Returns:
    A db.Text instance.
  """
  try:
    return db.Text(text, encoding='utf-8')
  except UnicodeDecodeError:
    return db.Text(text, encoding='latin-1')
