# -*- coding: utf-8 -*-
"""
    MoinMoin - "text/latex" Formatter

    Copyright 2005 Johannes Berg <johannes@sipsolutions.net>
    Copyright (c) 2003 by João Neves <moin@silvaneves.org>
    Copyright (c) 2000, 2001, 2002 by Jürgen Hermann <jh@web.de>

    All rights reserved, see COPYING for details.
"""

# Imports

import sys, re
from MoinMoin.formatter import FormatterBase
from MoinMoin.Page import Page

#############################################################################
### LaTeX Formatter
#############################################################################

class Formatter(FormatterBase):
    """
        Send text data.
    """

    hardspace = ' '

    def __init__(self, request, **kw):
        apply(FormatterBase.__init__, (self, request), kw)
        self.verbatim = False
        self.itemized = False

    def text2latex(self, text):
        "Escape special characters if not in verbatim mode"
        if self.verbatim: return text
        text = text.replace('\\', '$\\backslash$ ');
        text = text.replace('$', r'\$');
        text = text.replace(r'\$\backslash\$', r'$\backslash$')
        text = text.replace('#', r'\#');
        text = text.replace('%', r'\%');
        text = text.replace('^', r'\^{}');
        text = text.replace('&', r'\&');
        text = text.replace('_', r'\_');
        text = text.replace('{', r'\{');
        text = text.replace('}', r'\}');
        text = text.replace('~', r'\~{}');
        text = text.replace('"', r'\"{}');
        text = text.replace(u'ä', r'"a');
        text = text.replace(u'ü', r'"u');
        text = text.replace(u'ö', r'"o');
        text = text.replace(u'Ä', r'"A');
        text = text.replace(u'Ü', r'"U');
        text = text.replace(u'Ö', r'"O');
        text = text.replace(u'ß', r'\ss{}');
        return text

    def write_text(self, text):
      if self.item is None:
        return text
      else:
        self.item = (self.item[0], self.item[1]+text)
        return ''

    def startDocument(self, pagename):
        extra_preamble = ''
        preamble_page = self.request.pragma.get('latex_preamble', None)
        if preamble_page is not None:
          extra_preamble = Page(self.request, preamble_page).get_raw_body()
        extra_preamble = re.sub(re.compile('^#'), '%', extra_preamble)
        return """
\\documentclass[a4paper,12pt]{article}

\\usepackage[utf8]{inputenc}
\\usepackage{helvet}
\\usepackage{graphicx}
\\usepackage{multicol}
\\usepackage{fullpage}
\\usepackage{fancyhdr}
\\usepackage{multirow}
\\makeatletter
\\DeclareRobustCommand*\\textsubscript[1]{%%
  \\@textsubscript{\\selectfont#1}}
\\def\\@textsubscript#1{%%
  {\\m@th\\ensuremath{_{\\mbox{\\fontsize\\sf@size\\z@#1}}}}}
\\makeatother

%% begin extra preamble inclusion %%
%s

%% end extra preamble inclusion %%

\\title{%s}

\\author{ }

\\date{ }

\\renewcommand{\\theenumi}{\\arabic{enumi}}
\\renewcommand{\\theenumii}{\\arabic{enumi}.\\arabic{enumii}}
\\renewcommand{\\theenumiii}{\\arabic{enumi}.\\arabic{enumii}.\\arabic{enumiii}}
\\renewcommand{\\theenumiv}{\\arabic{enumi}.\\arabic{enumii}.\\arabic{enumiii}.\\arabic{enumiv}}

\\begin{document}
""" % (extra_preamble, pagename)

    def endDocument(self):
        return '\\end{document}\n'

    def sysmsg(self, text, **kw):
        return self.write_text('')

    def pagelink(self, on, pagename, text=None, **kw):
        return self.write_text('')

    def url(self, on, url=None, css=None, **kw):
        if not on:
            return self.write_text('}')
        if url[-4:] == '.pdf':
            nid = self.next_img_data
            self.next_img_data = ''
            return '\\includegraphics%s{' % nid
        url = url.replace('&', '\\&')
        return self.write_text('\\href{%s}{' % self.text2latex(url))

    def text(self, text):
        return self.write_text(self.text2latex(text))

    def rule(self, size=0):
        size = min(size, 10)
        ch = "---~=*+#####"[size]
        return self.write_text('\n\n\\hrulefill{}\n\n')

    def strong(self, on):
        return self.write_text(['{\\bf ', '}'][not on])

    def emphasis(self, on):
        return self.write_text(['{\\em ', '}'][not on])

    def highlight(self, on):
        return self.write_text(['{\\tt ', '}'][not on])

    def number_list(self, on, type=None, start=None):
        self.itemized = on
        if on:
            text = "\\begin{enumerate}"
        else:
            text = '\\end{enumerate}\n'
        return self.write_text(text)

    def bullet_list(self, on):
        self.itemized = on
        return self.write_text(['\\begin{itemize}\n', '\n\\end{itemize}\n'][not on])

    def listitem(self, on, **kw):
        if not self.itemized: return ''
        self._in_li = on != 0
        if on:
            return self.write_text('\\item ')
        else:
            return ''

    def sup(self, on):
        return self.write_text(['\\textsuperscript{', '}'][not on])

    def sub(self, on):
        return self.write_text(['\\textsubscript{', '}'][not on])

    def code(self, on, **kw):
        return self.write_text(['{\\tt ', '}'][not on])

    def code_area(self, on, code_id, code_type='code', show=0, start=-1, step=-1):
        res = self.preformatted(on)
        self.verbatim = False
        return self.write_text(res)

    def code_token(self, on, tok_type):
        return self.write_text('')

    def code_line(self, on):
        return self.write_text('\n')

    def preformatted(self, on):
        FormatterBase.preformatted(self, on)
        self.verbatim = on
        return self.write_text(['\\begin{verbatim}\n', '\\end{verbatim}\n'][not on])

    def smiley(self, text):
        return self.write_text(self.text2latex(text))

    def paragraph(self, on, **kw):
        FormatterBase.paragraph(self, on)
        return self.write_text(['', '\n\n'][not on])

    def linebreak(self, preformatted=1):
        if preformatted==1:
            return self.write_text('\n')
        else:
            return self.write_text('\\newline')

    def heading(self, on, depth, **kw):
        if depth == 1:
            rv = (r'\section{','}\n')
        elif depth == 2:
            rv = ('\\subsection{','}\n')
        elif depth == 3:
            rv = ('\\subsubsection{','}\n')
        else:
            rv = (r'\paragraph{','}\n',)
        return self.write_text(rv[not on])

    rows = []
    row = []
    item = None

    def table(self, on, attrs={}):
        def count_cols(row):
          cols = 0
          for cell in row:
            if cell[0].has_key('colspan'):
              cols += int(cell[0]['colspan'][1:-1])
            else:
              cols += 1
          return cols

        if on:
          self.rows = []
          self.item = None
          self.row = []
          return ''
        # not on:
        if self.rows == []: return ''
        cols = count_cols(self.rows[0])
        rows = len(self.rows)
        _table = [[0 for i in xrange(0,cols)] for j in xrange(0,rows)]
        _rownum = -1
        for _row in self.rows:
          _rownum += 1
          _cellnum = -1
          for _cell in _row:
            _cellnum += 1

            while _table[_rownum][_cellnum] is None or type(_table[_rownum][_cellnum]) == type(()):
              _cellnum += 1

            if _cell[0].get('rowspan') == '"1"':
              del _cell[0]['rowspan']
            if _cell[0].get('colspan') == '"1"':
              del _cell[0]['colspan']

            _rowspan = int(_cell[0].get('rowspan', '"1"')[1:-1])
            _colspan = int(_cell[0].get('colspan', '"1"')[1:-1])

            for j in xrange(0,_rowspan):
              for i in xrange(0,_colspan):
                _table[_rownum+j][_cellnum+i] = None
              _table[_rownum+j][_cellnum] = ({'colspan':'"%d"'%_colspan},None)
            _table[_rownum][_cellnum] = _cell


        table = '\\begin{tabular}{|%s}\n' % (cols * 'l|')
        for _row in _table:
          row = ''
          cellnum = 0
          _lines = []
          _do_line = True
          for _cell in _row:
            cellnum+=1
            if _cell == 0:
              return 'INVALID TABLE'
            if _cell is None:
              if _do_line:
                _lines += [cellnum]
              continue
            _rowspan = int(_cell[0].get('rowspan', '"1"')[1:-1])
            _colspan = int(_cell[0].get('colspan', '"1"')[1:-1])
            format = '%s'
            if not (_cell[1] is None):
              _do_line = True
              _lines += [cellnum]
            else:
              _do_line = False
              _cell = (_cell[0], u'')
            if _rowspan > 1:
              format = r'\multirow{%d}*{%%s}' % _rowspan
            if _colspan > 1:
              format = r'\multicolumn{%d}{|l|}{ %s }' % (_colspan, format)
            row += (format+' & ') % _cell[1].replace('\n',' ')
          for l in _lines:
            table += r'\cline{%d-%d}' % (l,l)
          table += row[0:-3] + '\\\\ \n'
        table += '\\hline\\end{tabular}\n\n'
        return table


    def table_row(self, on, attrs={}):
        if not on:
          self.rows += [self.row]
          self.row = []
        return ''

    def table_cell(self, on, attrs={}):
        if not on:
          self.row += [self.item]
          self.item = None
        else:
          self.item = (attrs,'')
        return ''

    def underline(self, on):
        return self.write_text(['\\underline{', '}'][not on])

    def definition_list(self, on):
        return self.write_text(['\\begin{description}\n', '\\end{description}\n'][not on])

    def definition_term(self, on, compact=0):
        return self.write_text(['\\item[', '] '][not on])

    def definition_desc(self, on):
        return self.write_text('')

    def attachment_image(self, fname, **kw):
        return self.image(src=fname)
    def image(self, **kw):
        # I am using alt for caption, but how to integrate the image?
        text = ''
        imgname = kw['src'].split('=')[-1]
        nid = self.next_img_data
        self.next_img_data = ''
        return '\\includegraphics%s{%s}' % (nid, imgname)
        #if kw.has_key('alt'):
        #    text += '\\begin{picture}\n'
        #    text += '\\caption{%s}\n' % kw[alt]
        #    text += '\\end{picture}\n'
        #return self.write_text(text)

    def crans_portal(self, entries):
        code = ''
        for pic, tit, bod in entries:
            code += "\\begin{minipage}{0.5\\linewidth}\n%s\\\\\n%s\n\\end{minipage}\n" % (tit, bod)
        return code

    def crans_box(self, tit, bod, color=None):
        return '%s\n%s' % (tit, bod)

    def johill_sidecall_emit_latex(self, code):
        # nothing else for now
        return code

    next_img_data = ''
    def johill_sidecall_next_image_data(self, data):
        self.next_img_data = '['+data+']'

    def open(self, on, **kw):
        return ""
    def close(self, on, **kw):
        return ""

    # suckers who call this. we can't do raw HTML, so we ignore it
    def rawHTML(self, markup):
        return ''
