# -*- coding: iso-8859-1 -*-
"""
    MoinMoin - show diff between 2 page revisions

    @copyright: 2010 Henryk Gerlach 
    @license: GNU GPL, see COPYING for details.
"""


import difflib
from MoinMoin import log
logging = log.getLogger(__name__)

from MoinMoin import wikiutil
from MoinMoin.logfile import editlog
from MoinMoin.Page import Page
from MoinMoin.widget import html

def execute(pagename, request):
    """ Handle "action=annotate"
        checking for parameter rev 
    """
    if not request.user.may.read(pagename):
        Page(request, pagename).send_page()
        return

    try:
        rev = int(request.values.get('rev', None))
    except StandardError:
        rev = None

    currentrev = Page(request, pagename).current_rev()
    if rev == None or rev > currentrev:
        rev = currentrev

    # spacing flag?
    ignorews = int(request.values.get('ignorews', 0))

    _ = request.getText


    def merge_annotation(oldlines, newlines, **kw):
        """
        Find changes between oldlines and newlines.
    
        @param oldlines: list of old decoration and text lines (decoration, line)
        @param newlines: list of new decoration and text lines (decoration, line)
        @keyword ignorews: if 1: ignore whitespace
        @rtype: list
        @return: changed old lines get replaced by new lines with new decoration
        """
        false = lambda s: None
        if kw.get('ignorews', 0):
            d = difflib.Differ(false)
        else:
            d = difflib.Differ(false, false)
    
        lines = list(d.compare( map(lambda s: s[1], oldlines), map(lambda s: s[1], newlines)))
    
        result = []
        iold = inew = 0
        for l in lines:
            if l[0] == " ":
                result.append( oldlines[iold] )
                iold += 1
                inew += 1
            if l[0] == "-": 
                iold+=1
            if l[0] == "+":
                result.append( newlines[inew] )
                inew += 1
        return result

    def annotate(rev):
        page   = Page(request, pagename, rev=rev)
        log    = page.editlog_entry()
        editor = log.getEditor(request) or _('N/A'),
        date   = request.user.getFormattedDateTime(wikiutil.version2timestamp(log.ed_time_usecs)) or _('N/A')
        return map(lambda l: [(rev, editor, date), l], page.get_raw_body().split("\n"))
    
    currrev = 1
    currtext = annotate(currrev)
    while currrev < rev:
        oldtext = currtext
        currrev += 1
        currtext = annotate(currrev)
        currtext = merge_annotation(oldtext, currtext, ignorews=ignorews)



    # build and send the page
    page = Page(request, pagename)
    def render_action(text, query, **kw):
        kw.update(dict(rel='nofollow'))
        return page.link_to(request, text, querystr=query, **kw)

    f = request.formatter
    if rev == currentrev:
        request.theme.send_title(_('Annotate for "%s"') % (pagename, ), pagename=pagename)
    else:
        request.theme.send_title(_('Annotate for "%s" revison %d') % (pagename, rev ), pagename=pagename)

    # Start content (important for RTL support)
    request.write(request.formatter.startContent("content"))

    request.write("<table><tr><th>"+_("Line")+"</th><th>"+_("Editor")+"</th><th>"+_("Date")+"</th><th>"+_("Rev")+"</th></tr>")
    for annotation, l in currtext:
        rev, editor, date = annotation
        request.write("<tr><td>") 
        request.write(f.text(l))
        request.write("</td><td>"+ editor[0] + "</td><td>"+date+"</td>")
        request.write("<td>"+render_action(_(str(rev)), {'action': 'recall', 'rev': '%d' % rev})+"</td></tr>")

    request.write("</table>")
    request.write(request.formatter.endContent())
    request.theme.send_footer(pagename)
    request.theme.send_closing_html()
