from Products.PortalTransforms.interfaces import itransform
from htmlentitydefs import entitydefs
import re


class HtmlToWebIntelligentPlainText:
    """Transform which replaces urls and email into hyperlinks"""

    __implements__ = itransform

    __name__ = "html_to_web_intelligent_plain_text"
    output = "text/x-web-intelligent"

    def __init__(self, name=None, inputs=('text/html',), tab_width = 4):
        self.config = { 'inputs' : inputs, 'tab_width' : 4}
        self.config_metadata = {
            'inputs' : ('list', 'Inputs', 'Input(s) MIME type. Change with care.'),
            'tab_width' : ('string', 'Tab width', 'Number of spaces for a tab in the input')
            }
        if name:
            self.__name__ = name
            
        self.preRegex = re.compile(r'<\s*pre[^>]*>(.*?)<\s*/pre\s*>', re.I | re.S)
        
        self.tagWhitespaceRegex = re.compile(r'\s+((<[^>]+>)\s+)+')
        self.whitespaceRegex = re.compile(r'\s+')
        
        self.tdRegex = re.compile(r'<\s*(td)([^>])*>', re.I)
        self.breakRegex = re.compile(r'<\s*(br)\s*/?>', re.I)
        self.startBlockRegex = re.compile(r'<\s*(dt)[^>]*>', re.I)
        self.endBlockRegex = re.compile(r'<\s*/\s*(p|div|tr|ul|ol|dl)[^>]*>', re.I)
        self.indentBlockRegex = re.compile(r'<\s*(blockquote|dd)[^>]*>', re.I)
        self.listBlockRegex = re.compile(r'<\s*(li)[^>]*>', re.I)

        self.tagRegex = re.compile(r'<[^>]+>', re.I | re.M)

    def name(self):
        return self.__name__

    def __getattr__(self, attr):
        if attr in self.config:
            return self.config[attr]
        raise AttributeError(attr)

    def convert(self, orig, data, **kwargs):
        text = orig
        
        # Save all <pre> sections and restore after other transforms
        preSections = {}
        def savePres(match):
            marker = '__pre_marker__%d__' % (len(preSections),)
            preSections[marker] = match.group(1)
            return marker
        if text is None:
            text = ''

        text = self.preRegex.sub(savePres, text)

        # Make whitespace-tag-whitespace into whitespace-tag. Repeat this 
        # in case there are directly nested tags
        def fixTagWhitespace(match):
            # Remove any superfluous whitespace, but preserve one leading space
            return ' ' + self.whitespaceRegex.sub('', match.group(0))
        text = self.tagWhitespaceRegex.sub(fixTagWhitespace, text)

        # Make all whitespace into a single space
        text = self.whitespaceRegex.sub(' ', text)

        # Fix entities
        text = text.replace('&nbsp;', ' ')
        for entity, letter in entitydefs.items():
            # Do &lt; and &gt; later, else we may be creating what looks like 
            # tags
            if entity != 'lt' and entity != 'gt':
                text = text.replace('&' + entity + ';', letter)

        # XXX: Remove <head>, <script>, <style> ?

        # Make tabs out of td's
        text = self.tdRegex.sub('\t', text)

        # Make br's and li's into newlines
        text = self.breakRegex.sub('\n', text)

        # Make the start of list blocks into paragraphs
        text = self.startBlockRegex.sub('\n\n', text)
    
        # Make the close of p's, div's and tr's into paragraphs
        text = self.endBlockRegex.sub('\n\n', text)

        # Make blockquotes and dd blocks indented
        text = self.indentBlockRegex.sub('\n\n  ', text)

        # Make list items indented and prefixed with -
        text = self.listBlockRegex.sub('\n\n  - ', text)

        # Remove other tags
        text = self.tagRegex.sub('', text)

        # Fix < and > entities
        text = text.replace('&lt;', '<')
        text = text.replace('&gt;', '>')

        # Restore pres
        for marker, section in preSections.items():
            text = text.replace(marker, '\n\n' + section + '\n\n')
        
        data.setData(text)
        return data

def register():
    return HtmlToWebIntelligentPlainText()
