from cgi import escape
from urllib import quote
import re

from .formats import BaseFormat, placeholder
from .tokens import *

_absolute_url_pattern = re.compile(r'^/|^\w+:/')

HTML_SIZES = {
    -4: '6pt',
    -3: '8pt',
    -2: '9pt',
    -1: '10pt',
    0: '12pt',
    1: '14pt',
    2: '18pt',
    3: '24pt',
    4: '30pt',
    5: '36pt'
    }

def urlquote(url):
    if isinstance(url,unicode):
        url = url.encode('utf-8')
    u = quote(url, '/:~#')
    if not _absolute_url_pattern.match(url):
        u = './'+u
    return u

class HTMLFormat(BaseFormat):

    def __init__(self):
        self.pclass = None

    def text(self, text):
        yield escape(text)
    
    def tag(self, t, arg=None):
        if t == BOLD:
            return u'b'
        elif t == ITALIC:
            return u'i'
        elif t == MONOSPACE:
            return u'tt'
        elif t == SUPERSCRIPT:
            return u'sup'
        elif t == SUBSCRIPT:
            return u'sub'
        elif t == UNDERLINE:
            return u'u'
        elif t == STRIKE:
            return u'strike'
        elif t == CODEBLOCK:
            return u'pre'
        elif t == HEADING:
            return u'h%s' % (arg,)
        elif t == TABLE_HEADING:
            return u'th'
        elif t == CENTER:
            return u'center'
        else:
            assert False, t
    LISTMAP = {ORDERED: 'ol', UNORDERED: 'ul',
               BLOCKQUOTE: 'blockquote'}
    def start(self, t, arg=None):
        if t in self.LISTMAP:
            tag = self.LISTMAP[t]
            start = (arg * 2 - 2) * ' '
            yield u'%s<%s>\n' % (start, tag)
        elif t in (ORDERED_ITEM, UNORDERED_ITEM):
            yield '%s<li>' % ((arg * 2 - 1) * ' ')
        elif t == BLOCKQUOTE_LINE:
            yield '%s' % ((arg * 2 - 1) * ' ')
        elif t == LINK:
            yield u'<a href="%s" class="%s">' % (urlquote(arg['url']),
                                                  quote(arg['style']))
        elif t == IMAGE:
            yield u'<img src="%s" class="%s" alt="' % (urlquote(arg['url']),
                                                        quote(arg['style']))
        elif t == PARAGRAPH:
            if self.pclass:
                yield u'<p class="%s">' % self.pclass
            else:
                yield u'<p>'
        elif t == TABLE:
            yield u'<table>\n'
        elif t == TABLE_ROW:
            yield u'<tr>'
        elif t == TABLE_CELL:
            argbit = ''
            if arg:
                if 'colspan' in arg:
                    argbit += ' colspan="%s"' % arg['colspan']
            yield u'<td%s>' % argbit
        elif t == FOOTNOTE:
            yield u'<small class="footnote">'
        elif t == RIGHT:
            yield u'<p class="right">'
        elif t == NOINDENT:
            yield u'<p class="noindent">'
        elif t == SIZE:
            yield u'<span style="font-size: %s">' % HTML_SIZES[arg]
        elif t == ERROR:
            yield u'<span class="error">'
        else:
            yield u'<%s>' % self.tag(t, arg)
    def end(self, t, arg=None):
        if t in self.LISTMAP:
            tag = self.LISTMAP[t]
            start = (arg * 2 - 2) * ' '
            if arg > 1:
                end = '\n'
            else:
                end = ''
            yield u'%s</%s>%s' % (start, tag, end)
        elif t in (ORDERED_ITEM, UNORDERED_ITEM):
            yield '</li>\n'
        elif t == BLOCKQUOTE_LINE:
            yield '\n'
        elif t == LINK:
            yield u'</a>'
        elif t == IMAGE:
            yield u'">'
        elif t == PARAGRAPH:
            self.pclass = None
            yield u'</p>'
        elif t == TABLE:
            yield u'</table>'
        elif t == TABLE_ROW:
            yield u'</tr>\n'
        elif t == TABLE_CELL:
            yield u'</td>'
        elif t == FOOTNOTE:
            yield u'</small>'
        elif t in (RIGHT, NOINDENT):
            yield u'</p>'
        elif t in (ERROR, SIZE):
            yield u'</span>'
        else:
            yield u'</%s>' % self.tag(t, arg)
    def entity(self, t, arg=None):
        if t == HRULE:
            yield u'<hr />'
        elif t == LINEBREAK:
            yield u'<br />'
        elif t == ENV_BREAK:
            # arg is False for a fake break (a context we couldn't break
            # paragraphs) and True for a real break (we closed the paragraph)
            if arg:
                yield u'\n\n'
            else:
                yield u'<br /><br />\n\n'
        elif t == NOINDENT:
            self.pclass = u'noindent'
        elif t == ERROR:
            for s in self.start(ERROR):
                yield s
            yield escape(arg)
            for s in self.end(ERROR):
                yield s
        elif t == REF:
            yield placeholder(arg)
        else:
            assert False, t

    def image(self, href, state, alt=None, info={}):
        OBJECT_FORMATS = ('.svg',)
        href = quote(href)
        dims = ''
        if 'width' in info:
            dims += ' width="%s"' % info['width']
        if 'height' in info:
            dims += ' height="%s"' % info['height']
        if alt:
            alt = escape(alt,quote=True)
            if info['style'] in OBJECT_FORMATS:
                yield u'<object data="%s" title="%s"%s>' % (href, alt, dims)
            yield u'<img src="%s" alt="%s" title="%s"%s />' % (href, alt, alt,
                                                               dims)
        else:
            if info['style'] in OBJECT_FORMATS:
                yield u'<object data="%s"%s>' % (href, dims)
            yield u'<img src="%s"%s />' % (href, dims)
        if info['style'] in OBJECT_FORMATS:
            yield u'</object>'
