# -*- coding: utf-8 -*- 

# lp4all: literate programming embedded in source code as wiki comments
# Copyright (C) 2006 Jean-Marie Favreau, Frédéric Lehobey, David Mentré
#                    and Thomas Petazzoni
# 
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
# 
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
# 
# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.

import re
import os.path
from tree_struct import *
from label_dict import *
from html_tools import *

class HtmlTreeRendering:
    def __init__(self, firstHeader = 2, listLevels = [], filename = ""):
        self.firstHeader = firstHeader
        self.listLevels = listLevels
        self.filename = filename

    def closeList(self):
        if self.listLevels == []:
            return ''
        raw_html = ''
        for i in self.listLevels:
            raw_html += '</li>\n</ul>\n'
        self.listLevels = []
        return raw_html + '<p>'

    def treeToHtml(self, tree):
        raw_html = '<p>' + self.treeToRawHtml(tree)
        return self.htmlClean(raw_html + self.closeList() + '</p>\n')

    def nodeToRawHtml(self, node):
        result = html_escape(node.text)
        for c in node.children:
            result += self.treeToRawHtml(c)
        return result

    def treeToRawHtml(self, tree):
        if tree.__class__ == NodeContentList:
            if self.listLevels == []:
                self.listLevels.append(tree.level)
                return '</p>\n<ul>\n<li>' + self.nodeToRawHtml(tree)
            else:
                if tree.level > self.listLevels[-1]:
                    self.listLevels.append(tree.level)
                    return '<ul>\n<li>' + self.nodeToRawHtml(tree)
                elif tree.level == self.listLevels[-1]:
                    return '</li>\n<li>' + self.nodeToRawHtml(tree)
                else:
                    raw_html = ''
                    while len(self.listLevels) != 1 and tree.level < self.listLevels[-1]:
                        raw_html += '</li>\n</ul>\n'
                        self.listLevels = self.listLevels[:-1]
                    self.listLevels[-1] = tree.level
                    return raw_html + "</li>\n<li>" + self.nodeToRawHtml(tree)
        elif tree.__class__ == NodeContentCancel:
            return '<span class="cancel">' + self.nodeToRawHtml(tree) + '</span>'
        elif tree.__class__ == NodeContentPre:
            return '<pre>' + self.nodeToRawHtml(tree) + '</pre>\n'
        elif tree.__class__ == NodeContentCode:
            return '<code>' + self.nodeToRawHtml(tree) + '</code>'
        elif tree.__class__ == NodeContentEmphasize:
            return '<em>' + self.nodeToRawHtml(tree) + '</em>'
        elif tree.__class__ == NodeContentStrong:
            return '<strong>' + self.nodeToRawHtml(tree) + '</strong>'
        elif tree.__class__ == NodeContentTitle:
            return self.closeList() + '</p>\n<h' + str(self.firstHeader + tree.level) + '>' + self.nodeToRawHtml(tree) + '</h' + str(self.firstHeader + tree.level) + '>\n<p>'
        elif tree.__class__ == NodeContentNewLine:
            return self.closeList() + '</p>\n<p>'
        elif tree.__class__ == NodeContentRef:
            try:
                label = LabelDict.getSingleton().find(tree.uri)
            except KeyError:
                print "WARNING: Label '%s' doesn't exist" % tree.uri
                return '<a href="#%s" class="broken">%s</a>' % (tree.uri,
                                                                self.nodeToRawHtml(tree))
            return '<a href="%s#%s">%s</a>' % (self.findTargetLink(self.filename, label.file),
                                               tree.uri,
                                               self.nodeToRawHtml(tree))
        elif tree.__class__ == NodeContentLabel:
            return '<a id="%s"></a>' % tree.text
        elif tree.__class__ == NodeContentLink:
            return '<a class="external" href="' + tree.uri + '">' + self.nodeToRawHtml(tree) + '</a>'
        elif tree.__class__ == NodeContentText:
            return self.nodeToRawHtml(tree)
        elif tree.__class__ == NodeContentHR:
            return '</p><hr /><p>'
        else:
            result = ''
            for c in tree.children:
                result += self.treeToRawHtml(c)
            return result

    def removeCommonPrefix(self, a, b):
        if a == [] or b == []:
            return (a, b)
        if a[0] == b[0]:
            return self.removeCommonPrefix(a[1:], b[1:])
        return (a, b)

    # Given a source filename and a target filename, return the simplest
    # link from source to target
    def findTargetLink(self, sourceFilename, targetFilename):
        assert sourceFilename == os.path.normpath(sourceFilename)
        assert targetFilename  == os.path.normpath(targetFilename)
        source, target = self.removeCommonPrefix(sourceFilename.split('/'),
                                                 targetFilename.split('/'))
        targetRemaining = ""
        for e in target:
            targetRemaining = os.path.join(targetRemaining, e)
        if targetRemaining != "":
            return os.path.join("../" * (len(target)-1), targetRemaining + ".html")
        else:
            return ""


    def htmlCleanEmplyTag(self, html_code, tag):
        return re.sub("<" + tag + ">[ \t\n]*</" + tag + ">", "", html_code)

    # Removes empty <p></p>, <li></li>, <ul></ul> and various other
    # html tags
    def htmlClean(self, html_code):
        clean_html = self.htmlCleanEmplyTag(html_code, 'p')
        for i in [0, 1, 2]:
            clean_html = self.htmlCleanEmplyTag(clean_html, 'h' + str(self.firstHeader + i))
        clean_html = self.htmlCleanEmplyTag(clean_html, "strong")
        clean_html = self.htmlCleanEmplyTag(clean_html, "em")

        l = -1
        while l != len(clean_html):
            clean_html = self.htmlCleanEmplyTag(clean_html, "li")
            clean_html = self.htmlCleanEmplyTag(clean_html, "ul")
            l = len(clean_html)

        return clean_html