"""
    MoinMoin - Linux-Magazin Artikel Parser

    Copyright (c) 2002 by Jürgen Hermann <jh@web.de>

    Siehe http://www.linux-magazin.de/Info/Hinweise/Format.html
    für Details zum hier unterstützten Format.
"""

import re


class Parser:
    """ Parser für das "Autoren-Format" des Linux-Magazins.
    """

    PARA_SECTIONS = ('L', 'KL', 'IL')

    def __init__(self, raw, request, **kw):
        self.raw = raw
        self.request = request
        self.metadata = {}

        self.request.setPragma('section-numbers', 'off')

    def format(self, formatter):
        """ Den Text formatiert ausgeben.
        """
        self.formatter = formatter
        self.formatter._base_depth = 1

        # Text in Zeilen aufbereiten
        text = self.raw
        text = text.expandtabs()
        text = [line.rstrip() for line in text.splitlines()]

        # Zeilen zu Abschnitten verarbeiten
        sections = []
        collecting = 0
        for line in text:
            if not line:
                if collecting and sections[-1][0] in ('LI',):
                    # Leerzeilen in Listings sammeln
                    sections[-1][1].append(line)
                else:    
                    # Ende des Abschnitts
                    collecting = 0
            elif line[0] == "@":
                # Kennung verarbeiten
                try:
                    sect, line = line[1:].split(':', 1)
                except ValueError:
                    sect = 'L'
                if sect == '#': continue
                sections.append((sect, [line]))
                collecting = 1
            else:
                # Fließtext
                if not sections:
                    sections.append(('L', []))
                elif not collecting:
                    sections.append((sections[-1][0], []))
                collecting = 1
                sections[-1][1].append(line)

        # Listen erkennen, Kasten einsammeln
        idx = 0
        while idx < len(sections):
            if sections[idx][0] in self.PARA_SECTIONS and sections[idx][1][0].startswith('* '):
                base = idx
                sections[base] = ('_UL', [' '.join(sections[base][1])[2:]])
                idx += 1
                while idx < len(sections) and sections[idx][0] in self.PARA_SECTIONS and sections[idx][1][0].startswith('* '):
                    sections[base][1].append(' '.join(sections[idx][1])[2:])
                    idx += 1
                sections[base+1:idx] = []
                idx = base+1
            else:
                idx += 1                
        idx = 0
        while idx < len(sections):
            if sections[idx][0] == 'KT':
                base = idx
                while idx < len(sections) and sections[idx][0] not in ('L', 'KE'):
                    idx += 1
                sections[base:idx] = [('_Kasten', sections[base:idx])]
            else:
                idx += 1                

        # Abschnitte ausgeben
        self.output = []
        self.renderSections(sections)

        self.output[0:0] = ([
            self.formatter.heading(1, self.metadata['T']),
            self.formatter.heading(2, '%(D)s [%(R)s/%(SW)s]' % self.metadata),
            self.formatter.text('von '),
            self.formatter.strong(1),
            self.formatter.text(self.metadata['A']),
            self.formatter.strong(0),
        ])            

        self.request.write(''.join(self.output))

    def renderSections(self, sections):
        for section in sections:
            handler = getattr(self, '_render' + section[0], self._unknown)
            handler(section)

    def _inline(self, lines):
        "Inline-Markup verarbeiten"
        result = []
        flags = {'I': 0, 'B': 0, 'C': 0, '+': 0, '-': 0, 'U': 0}
        calls = {
            'I': self.formatter.emphasis,
            'B': self.formatter.strong,
            'C': self.formatter.code,
            '+': self.formatter.sup,
            '-': self.formatter.sub,
        }
        markup = filter(None, re.split(r'(<[IBC+-U]>)', ' '.join(lines)))
        for part in markup:
            if part.startswith('<'):
                flags[part[1]] ^= 1
                if part == '<U>':
                    if not flags['U']:
                        result.append(self.formatter.url(result[-1]))
                        result[-2] = self.formatter.text('[')
                        result.append(self.formatter.text(']'))
                else:
                    result.append(calls[part[1]](flags[part[1]]))
            else:
                result.append(self.formatter.text(part))
        return result

    def _paragraph(self, lines):
        return ['\n', self.formatter.paragraph(1)] + \
            self._inline(lines) + [self.formatter.paragraph(0), '\n']

    def _unknown(self, section):
        self.output.append(self.formatter.sysmsg('Unbekannter Absatztyp "%s"' % section[0]))
        self.output.extend(self._paragraph(section[1]))

    def _meta(self, section):
        self.metadata[section[0]] = '\n'.join(section[1])

    _renderR = _meta # Rubrik
    _renderSW = _meta # Schlagwort
    _renderD = _meta # Dachzeile
    _renderT = _meta # Titel
    _renderA = _meta # Autor

    def _renderV(self, section):
        "Vorspann"
        para = self._paragraph(section[1])
        para.insert(2, self.formatter.emphasis(1))
        para.insert(len(para)-2, self.formatter.emphasis(0))
        para.append(self.formatter.rule())
        self.output.extend(para)

    def _render_UL(self, section):
        self.output.append(self.formatter.bullet_list(1))
        for item in section[1]:
            self.output.append(self.formatter.listitem(1))
            self.output.extend(self._inline([item]))
            self.output.append(self.formatter.listitem(0))
        self.output.append(self.formatter.bullet_list(0))

    def _renderL(self, section):
        "Lauftext"
        self.output.extend(self._paragraph(section[1]))

    def _render_Kasten(self, section):
        self.output.extend([
            self.formatter.paragraph(1),
            self.formatter.table(1),
            self.formatter.table_row(1),
            self.formatter.table_cell(1, attrs={'bgcolor': '#E8E8E8'}),
        ])
        self.renderSections(section[1])
        self.output.extend([
            self.formatter.table_cell(0),
            self.formatter.table_row(0),
            self.formatter.table(0),
            self.formatter.paragraph(0),
        ])

    def _renderKT(self, section):
        "Kastentitel"
        self.output.extend([
            self.formatter.strong(1),
            self.formatter.text('\n'.join(section[1])),
            self.formatter.strong(0),
            self.formatter.linebreak(0),
        ])

    _renderKL = _renderL

    def _renderKE(self, section):
        "Kastenende"

    def _renderZT(self, section):
        "Zwischentitel"
        self.output.append(self.formatter.heading(2, ' '.join(section[1])))

    def _renderLI(self, section):
        "Listing"
        self.output.extend([
            self.formatter.preformatted(1),
            self.formatter.text('\n'.join(section[1])),
            self.formatter.preformatted(0),
        ])

    def _renderBi(self, section):
        "Bild"
        from MoinMoin.action.AttachFile import getAttachUrl

        self.output.extend([
            self.formatter.paragraph(1),
            self.formatter.table(1),
            self.formatter.table_row(1),
            self.formatter.table_cell(1, attrs={'bgcolor': '#E8E8E8'}),
        ])
        ##self.output.append(self.formatter.rule())
        self.output.append(self.formatter.url(getAttachUrl(self.formatter.page.page_name, section[1][0])))
        
    def _renderB(self, section):
        "Bildunterschrift"
        self.output.extend([
            ##self.formatter.rule(),
            self.formatter.linebreak(0),
            self.formatter.strong(1),
            self.formatter.text('\n'.join(section[1])),
            self.formatter.strong(0),
            self.formatter.table_cell(0),
            self.formatter.table_row(0),
            self.formatter.table(0),
            self.formatter.paragraph(0),
        ])

    def _renderIT(self, section):
        "Infotitel"
        self.output.append(self.formatter.heading(2, ' '.join(section[1])))

    _renderIL = _renderL
    _renderIE = _renderKE

