import sys, re

from bazbase.wiki import (macros,environment,illegal,divided,
                          WikiException, NoContentException,
                          safesplit, parse_macro_args, recurse,
                          baz_eval, full_eval, leafprop, render_propval,
                          render_allow_override, get_format,
                          get_element, get_current_element, get_propname,
                          get_topthis, get_context,
                          atom, eoverride, moverride, context,
                          makeRestricted, tokens_text)
from bazbase.flavors import FORMATS

from redbeans.tokens import *

from . import custom

def moverride_thunk(ename, pname, form):
    with moverride(dict(form=form)):
        for t in recurse(ename, pname):
            yield t

def get_headfoot(form, ename):
    return (moverride_thunk(ename, u'topleft', form),
            moverride_thunk(ename, u'topright', form),
            moverride_thunk(ename, u'bottomleft', form),
            moverride_thunk(ename, u'bottomright', form))

def html_div_headers(headfoot):
    yield Literal('<div class="lheader">')
    for t in headfoot[0]:
        yield t
    yield Literal('</div>')
    yield Literal('<div class="rheader">')
    for t in headfoot[1]:
        yield t
    yield Literal('</div>')
    yield Literal('<div class="lfooter">')
    for t in headfoot[2]:
        yield t
    yield Literal('</div>')
    yield Literal('<div class="rfooter">')
    for t in headfoot[3]:
        yield t
    yield Literal('</div>')
def html_table_header(headfoot):
    yield Literal('<tr class="head"><td>')
    for t in headfoot[0]:
        yield t
    yield Literal('</td><td>')
    for t in headfoot[1]:
        yield t
    yield Literal('</td><td></td><td></td></tr>')
def html_table_footer(headfoot):
    yield Literal('<tr class="foot"><td>')
    for t in headfoot[2]:
        yield t
    yield Literal('</td><td>')
    for t in headfoot[3]:
        yield t
    yield Literal('</td><td></td><td></td></tr>')
def latex_cmd_headers(headfoot):
    yield Literal('\\lhead{')
    for t in headfoot[0]:
        yield t
    yield Literal('}\\rhead{')
    for t in headfoot[1]:
        yield t
    yield Literal('}\\lfoot{')
    for t in headfoot[2]:
        yield t
    yield Literal('}\\rfoot{')
    for t in headfoot[3]:
        yield t
    yield Literal('}\n')
def latex_arg_headers(headfoot):
    first = True
    for hf in headfoot:
        if not first:
            yield Literal('}{')
        else:
            first = False
        for t in hf:
            yield t

def form(argstr, content=None):
    """Placeholder that evaluates to 'sheet' or 'card' or 'badge' when
    evaluating headers and footers."""
    return ""
macros.form = form

def sheet(argstr, content):
    """Render content as a sheet.  Takes an element to get headers and
    footers from, and optionally a 'color' parameter for paper color."""
    args = parse_macro_args(argstr)
    color = ""
    headfoot = [(),(),(),()]
    for key,val in args.items():
        if key == 'color':
            color = baz_eval(val).strip()
        elif key == 1:
            headfoot = get_headfoot(u'sheet', val)
        else:
            raise WikiException("Unknown arg '%s' in sheet!"
                                % (key))
    if not color.strip():
        color = "white"
    if get_format() == FORMATS['html']:
        yield Literal('<div class="sheet %s">' % color)
        for t in html_div_headers(headfoot):
            yield t
        for t in content:
            yield t
        yield Entity(ENV_BREAK, True)
        yield Literal('</div>')
    elif get_format() == FORMATS['tex']:
        yield Literal('\\begin{sheet}\n')
        for t in latex_cmd_headers(headfoot):
            yield t
        for t in content:
            yield t
        yield Entity(ENV_BREAK, True)
        yield Literal('\n\\end{sheet}')
    else:
        for t in content:
            yield t
macros.sheet = sheet

def card(argstr, content):
    """Render content as a card.  Takes an element to get headers and
    footers from, and optionally a 'color' parameter for paper color
    and a 'size' parameter."""
    parts = safesplit(content, ('flip',))
    args = parse_macro_args(argstr)
    color = ""
    size = ""
    headfoot = [(),(),(),()]
    for key,val in args.items():
        if key == 'color':
            color = baz_eval(val).strip()
        elif key == 'size':
            size = " "+baz_eval(val).strip()
        elif key == 1:
            headfoot = get_headfoot(u'card', val)
        else:
            raise WikiException("Unknown arg '%s' in card!"
                                % (key))
    if not color.strip():
        color = "white"
    if len(parts) > 2:
        raise WikiException("More than one ##flip## in a ##card##!")
    else:
        if len(parts) < 2:
            front = parts[0]
            back = ""
        else:
            front,back = parts
        if get_format() == FORMATS['html']:
            yield Literal('<table class="card %s%s">\n' % (color, size))
            for t in html_table_header(headfoot):
                yield t
            yield Literal('<tr class="body">\n<td colspan="2">\n')
            for t in front:
                yield t
            yield Literal('\n</td>\n')
            yield Literal('<td colspan="2">\n')
            for t in back:
                yield t
            yield Literal('\n</td>\n</tr>\n')
            for t in html_table_footer(headfoot):
                yield t
            yield Literal('</table>\n')
        elif get_format() == FORMATS['tex']:
            yield Literal('\\begin{card}%s\n'
                          % ("[%s]" % size.strip() if size.strip() else ""))
            yield Literal('\\front{')
            for t in latex_cmd_headers(headfoot):
                yield t
            for t in front:
                yield t
            yield Literal('}\n\\back{')
            for t in back:
                yield t
            yield Literal('}\n\\end{card}\n')
        else:
            for t in front:
                yield t
            yield Entity(ENV_BREAK)
            for t in back:
                yield t

macros.card = card
macros.flip = illegal('flip', 'card', 'sign')

def packet(argstr,content):
    """Render content as a packet.  Takes a label for the outside and
    an element to get headers and footers from, and optionally a
    'color' parameter for paper color and a 'style' parameter ("envelope"
    or "folding")."""
    args = parse_macro_args(argstr)
    label = ""
    color = ""
    style = "Envelope"
    headfoot = [(), (), (), ()]
    for key,val in args.items():
        if key == 'color':
            color = baz_eval(val).strip()
        elif key == 1:
            label = full_eval(val)
        elif key == 2:
            headfoot = get_headfoot(u'packet', val)
        elif key == 'style':
            style = baz_eval(val).strip().capitalize()
            if style not in ("Envelope","Folding"):
                raise WikiException('The only valid packet styles are "envelope" and "folding"!')
        else:
            raise WikiException("Unknown arg '%s' in packet!"
                                % (key))
    if not color.strip():
        color = "white"
    if get_format() == FORMATS['html']:
        yield Literal('<table class="card packet %s %s">\n' % (style.lower(),
                                                               color))
        for t in html_table_header(headfoot):
            yield t
        yield Literal('<tr class="body">\n<td colspan="2">\n')
        for t in label:
            yield t
        yield Literal('\n</td>\n')
        yield Literal('<td colspan="2">\n')
        for t in content:
            yield t
        yield Literal('\n</td>\n</tr>\n')
        for t in html_table_footer(headfoot):
            yield t
        yield Literal('</table>\n')
    elif get_format() == FORMATS['tex']:
        yield Literal('\\%sPacket{' % (style,))
        for t in latex_arg_headers(headfoot):
            yield t
        yield Literal('}{')
        for t in label:
            yield t
        yield Literal('}{')
        for t in content:
            yield t
        yield Literal('}')
    else:
        yield Text(u"Packet: ")
        for t in label:
            yield t
macros.packet = packet

def notebook(argstr,content):
    args = parse_macro_args(argstr)
    front = ""
    color = ""
    headfoot = [(), (), (), ()]
    for key,val in args.items():
        if key == 'color':
            color = baz_eval(val).strip()
        elif key == 1:
            front = full_eval(val)
        elif key == 2:
            headfoot = get_headfoot(u'notebook', val)
        else:
            raise WikiException("Unknown arg '%s' in notebook!"
                                % (key))
    if not color.strip():
        color = "white"
    if get_format() == FORMATS['html']:
        yield Literal('<div class="notebook %s">\n' % (color))
        yield Literal('<div class="front">')
        for t in html_div_headers(headfoot):
            yield t
        for t in front:
            yield t
        yield Literal('</div>')
        for t in content:
            yield t
        yield Literal('</div>\n')
    elif get_format() == FORMATS['tex']:
        yield Literal('\\startnotebook{')
        for t in latex_arg_headers(headfoot):
            yield t
        yield Literal('}{')
        for t in front:
            yield t
        yield Literal('}')
        for t in content:
            yield t
        yield Literal('\n\\endnotebook\n')
    else:
        yield Text(u"Notebook: ")
        for t in front:
            yield t
macros.notebook = notebook
def page(argstr,content):
    """Dummy page for previewing outside a notebook."""
    args = parse_macro_args(argstr)
    if 1 in args:
        title = baz_eval(argstr).strip()
    else:
        title = getattr(get_format(), 'gknextpage', 1)
        get_format().gknextpage = title+1
        title = unicode(title)
    if get_format() == FORMATS['html']:
        yield Literal('<div><h2>')
        yield Text(title)
        yield Literal('</h2>\n')
        for t in content:
            yield t
        yield Literal('</div>')
    elif get_format() == FORMATS['tex']:
        yield Literal(r"\begin{nbpage}{")
        yield Text(title)
        yield Literal('}\n')
        for t in content:
            yield t
        yield Literal('\n\\end{nbpage}\n')
    else:
        yield Start(HEADING, 2)
        yield Text(title)
        yield End(HEADING, 2)
        for t in content:
            yield t
macros.page = page

def badge(argstr,content):
    args = parse_macro_args(argstr)
    color = ""
    style = "light"
    headfoot = [(), (), (), ()]
    for key,val in args.items():
        if key == 'color':
            color = baz_eval(val).strip()
        elif key == 1:
            headfoot = get_headfoot(u'badge', val)
        elif key == 'style':
            style = baz_eval(val).strip()
            if style not in ("light", "dark", "simple", "mini"):
                raise WikiException('The only valid badge styles are "light" and "dark"!')
        else:
            raise WikiException("Unknown arg '%s' in badge!"
                                % (key))
    if not color.strip():
        color = "white"
    if get_format() == FORMATS['html']:
        yield Literal('<div class="badge %s %s">\n' % (style.lower(), color))
        for t in html_div_headers(headfoot):
            yield t
        for t in content:
            yield t
        yield Literal('</div>\n')
    elif get_format() == FORMATS['tex']:
        yield Literal('\\NameBadge[%s]{' % (style,))
        for t in latex_arg_headers(headfoot):
            yield t
        yield Literal('}{')
        for t in content:
            yield t
        yield Literal('}')
    else:
        yield Text(u"Badge: ")
        for t in content:
            yield t
macros.badge = badge

def sign(argstr,content):
    args = parse_macro_args(argstr)
    parts = safesplit(content, ('flip',))
    assert len(parts) in (1, 2), parts
    name = None
    color = u""
    size = None
    location = u""
    blurb = None
    headfoot = [(), (), (), ()]
    for key,val in args.items():
        if key == 'color':
            color = baz_eval(val).strip()
        elif key == 'blurb':
            blurb = [Text(baz_eval(val).strip())]
        elif key == 'location':
            location = baz_eval(val).strip()
        elif key == 'size':
            size = baz_eval(val).strip()
        elif key == 1:
            headfoot_ename = val
            headfoot = get_headfoot(u'sign', val)
        elif key == 2:
            name = [[Text(baz_eval(val).strip())]] * 2
        else:
            raise WikiException("Unknown arg '%s' in packet!"
                                % (key))
    if not color.strip():
        color = "white"
    if name is None:
        name = [moverride_thunk(headfoot_ename, u'name', u'sign')]
        if len(parts) == 2:
            name.append(moverride_thunk(headfoot_ename, u'name', u'signback'))
    if blurb is None:
        blurb = moverride_thunk(headfoot_ename, u'blurb', u'sign')
    if size is None:
        size = baz_eval(u'%s.%s' % (headfoot_ename, u'size'))
    size = size.capitalize()
    if size not in ("Big","Medium","Small"):
        raise WikiException("Sign size must be big, medium, or small, not %s!"
                            % size)
    if get_format() == FORMATS['html']:
        for i in xrange(len(parts)):
            yield Literal('<div class="sign %s %s">\n' % (size.lower(), color))
            for t in html_div_headers(headfoot):
                yield t
            yield Literal('<h1 class="name">')
            for t in name[i]:
                yield t
            yield Literal('</h1>')
            yield Literal('<div class="content">\n')
            for t in parts[i]:
                yield t
            yield Literal('</div>\n')
            yield Literal('<div class="blurb">')
            for t in blurb:
                yield t
            yield Literal('</div>\n')
        yield Literal('</div>\n')
    elif get_format() == FORMATS['tex']:
        yield Literal(r'\headfoot{')
        for t in latex_arg_headers(headfoot):
            yield t
        yield Literal('}\\Sign[\\%s]{' % (size,))
        for t in name[0]:
            yield t
        yield Literal('}{')
        yield Text(location)
        yield Literal('}{')
        for t in parts[0]:
            yield t
        yield Entity(ENV_BREAK, True)
        yield Literal('}{')
        if len(parts) > 1:
            for t in name[1]:
                yield t
            yield Literal('}{')
            for t in parts[1]:
                yield t
            yield Entity(ENV_BREAK, True)            
        else:
            yield Literal('}{')
        yield Literal('}{')
        for t in blurb:
            yield t
        yield Literal('}')
    else:
        yield Text(u'Sign: ')
        for t in content:
            yield t
macros.sign = sign

def pagefold(argstr, content):
    args = parse_macro_args(argstr)
    parts = safesplit(content, ('break',))
    headfoot_ename = args.pop(1)
    headfoot = get_headfoot(u'pagefold', headfoot_ename)
    assert len(args) == len(parts)

    if get_format() == FORMATS['tex']:
        yield Literal('\\begin{pagefold}\n')
        for t in latex_cmd_headers(headfoot):
            yield t
        total = 0
        flipped = False
        for i in xrange(len(parts)):
            part = parts[i]
            height = int(args[i + 2])
            yield Literal(r'\pfpart{')
            yield Literal(str((height / 100.) * 10.3))
            yield Literal(r'in}{')
            for t in part:
                yield t
            yield Literal('}\n')
            total += height
            if total == 100:
                if not flipped:
                    yield Literal('\\clearpage\n')
                    flipped = True
                total = 0
            elif total > 100:
                raise WikiException("Pagefold side doesn't add up to 100!")
            else:
                yield Literal('\\hrule\n')
        yield Literal('\\end{pagefold}\n')
    else:
        # TODO(xavid): cleaner HTML version.
        for part in parts:
            for t in part:
                yield t
            yield Entity(HRULE)
            
macros.pagefold = pagefold
macros.upsidedown = environment('upsidedown', texmode='command')

#macros.header = divided('header','gap','left','right')
#macros.footer = divided('footer','gap','left','right')
#macros.gap = illegal('gap','header','footer')

def imageheader(argstr, content=None):
    args = parse_macro_args(argstr)
    if 1 not in args or 2 not in args or 3 not in args or len(args) != 3:
        raise WikiException(
            "##imageheader## takes exactly 3 parameters!")
    if content is None:
        raise NoContentException("##imageheader## needs content!")
    width = baz_eval(args[2]).strip()
    height = baz_eval(args[3]).strip()
    img = Entity(IMAGE, "%s^d%sx%s" % (args[1], width, height))

    if get_format() == FORMATS['html']:
        yield Literal('<table class="imageheader"><tr>\n')
        yield Literal('<td>')
        yield img
        yield Literal('</td>\n')
        yield Literal('<th>\n')
        for t in content:
            yield t
        yield Literal('</th>\n')
        yield Literal('</tr></table>\n')
    elif get_format() == FORMATS['tex']:
        yield Literal('\\imageheader{')
        yield img
        yield Literal('}{%spx}{%spx}{' % (width, height))
        for t in content:
            yield t
        yield Literal('}')
    else:
        yield Start(HEADER, 1)
        for t in content:
            yield t
        yield End(HEADER, 1)
macros.imageheader = imageheader

macros.secret = environment(
    'secret', doc="""Mark this content as secret, for printing.""")

def labels(argstr, content):
    args = parse_macro_args(argstr)
    h = baz_eval(args[1])
    w = baz_eval(args[2])
    v_margin = baz_eval(args[3])
    h_margin = baz_eval(args[4])
    if 5 in args:
        v_gap = baz_eval(args[5])
    else:
        v_gap = 0
    if 6 in args:
        h_gap = baz_eval(args[6])
    else:
        h_gap = 0
    
    if get_format() == FORMATS['tex']:
        rows = int(11. / (h + v_gap))
        cols = int(8.5 / (w + h_gap))
        yield Literal('\\LabelCols=%s\n' % cols)
        yield Literal('\\LabelRows=%s\n' % rows)
        yield Literal('\\LeftPageMargin=%sin\n' % h_margin)
        yield Literal('\\RightPageMargin=%sin\n' % h_margin)
        yield Literal('\\TopPageMargin=%sin\n' % v_margin)
        yield Literal('\\BottomPageMargin=%sin\n' % v_margin)
        yield Literal('\\InterLabelColumn=%sin\n' % h_gap)
        yield Literal('\\InterLabelRow=%sin\n' % v_gap)
        yield Literal('\\LabelSetup\n')
        for t in content:
            if t.style == UNORDERED_ITEM:
                if t.op == START:
                    yield Literal(r'\addresslabel{\centering ')
                elif t.op == END:
                    yield Literal('}\n')
                else:
                    assert False, t
            else:
                yield t
    else:
        for t in content:
            yield t

macros.labels = labels

def current_run():
    return '1'

def runtime(argstr):
    ename, propname = argstr.split('.', 1)
    element = get_element(ename)
    propname = get_propname(propname)
    propval = element[propname]

    run = current_run()
    if propval.has_overlay(run):
        yield Start(STRIKE)
        yield Entity(MACRO, ('%s.%s' % (ename, propname), None))
        yield End(STRIKE)
        yield Text(u' ')
        yield Start(BOLD)
        yield Text(propval.get_overlay(run))
        yield End(BOLD)
    else:
        for t in recurse(ename, propname): yield t
macros.runtime = runtime

def todo(argstr, content=None):
    makeRestricted()
    yield Start(BOLD)
    yield Start(ITALIC)
    yield Text(u"TODO: ")
    if argstr:
        yield Text(argstr)
    if content:
        for t in content:
            yield t
    yield Text(u" :TODO")
    yield End(ITALIC)
    yield End(BOLD)
macros.todo = todo
macros.TODO = todo

def quote(start, end=None):
    def env(argstr, content):
        parts = safesplit(content, ('break',))
        if len(parts) > 2:
            raise WikiException("Too many parts in a quote!")
        yield start
        yield Start(ITALIC)
        for t in parts[0]:
            yield t
        yield End(ITALIC)
        if end is not None:
            yield end
        if len(parts) > 1:
            yield Start(RIGHT)
            yield Start(ITALIC)
            for t in parts[1]:
                yield t
            yield End(ITALIC)
            yield End(RIGHT)
    return env
macros.cenquote = quote(Start(CENTER), End(CENTER))
macros.bigquote = quote(Entity(NOINDENT))

def contexteval(argstr):
    """Call as {{{<<contexteval leaf args content/>>}}} in an element's
    substitution to allow that element to serve as a context for
    name/pronoun/prop evaluation."""
    args = parse_macro_args(argstr)
    if 1 not in args or 2 not in args or 3 not in args or len(args) != 3:
        raise WikiException(
            "##contexteval## takes exactly 3 parameters!")
    ename = args[1]
    current = get_element(ename)
    carg = render_allow_override(current, args[2])
    ccontent = render_allow_override(current, args[3])

    # This is for members/contacts lists.
    is_refs = False
    #print >>sys.stderr, "contexteval", get_context()
    if get_context('in_get_refs'):
        is_refs = True
        yield Start(LINK, ename)

    with context({'in_get_refs': False}):
        with eoverride({u'current': current}):
            if ccontent is not None:
                cnt = 0
                for t in ccontent(None, None):
                    cnt += 1
                    yield t
                if cnt == 0:
                    for t in recurse(ename, u'name'): yield t
            elif carg:
                yield Entity(MACRO, (carg, None))
            else:
                for t in recurse(ename, u'name'): yield t

    if is_refs:
        yield End(LINK, ename)
macros.contexteval = contexteval

GENDER_CONV_MAP = {'?': 'A'}

def pronoun_helper(mfna):
    e = get_current_element()
    assert e is not None
    genderp = u'gender'
    gen = render_allow_override(e, genderp, '?')[0:1].upper()
    if 'A' not in mfna:
        mfna['A'] = mfna['M'] + [Text(u'/')] + mfna['F']
    if gen in GENDER_CONV_MAP:
        gen = GENDER_CONV_MAP[gen]
    if gen in mfna:
        return mfna[gen]
    else:
        return mfna['A']

def mfn_generic(*order):
    def mfn(argstr, content):
        parts = safesplit(content, ('break',))
        mfna = {}
        for x in xrange(min(len(order), len(parts))):
            mfna[order[x]] = parts[x]
        return pronoun_helper(mfna)
    return mfn
macros.mf = macros.mfn = mfn_generic('M', 'F', 'N')
macros.fm = macros.fmn = mfn_generic('F', 'M', 'N')

def pronoun(**mfna):
    for k in mfna:
        mfna[k] = [Text(unicode(mfna[k]))]
    def pn(argstr, content=None):
        return pronoun_helper(mfna)
    return pn
# Helpers
def _pron(mac, M, F, **mfna):
    mfna['M'] = M
    mfna['F'] = F
    # Doing this explicitly causes the uppercasing to DTRT.
    if 'A' not in mfna:
        mfna['A'] = '%s/%s' % (M, F)
    if 'S' not in mfna and mac.startswith('th'):
        mfna['S'] = mac[2:]
    for a in [mac] + mfna.values():
        if not hasattr(macros, a):
            pn = pronoun(**mfna)
            if a == mac:
                pn.hidden = 'pronoun'
            else:
                pn.hidden = 'pronounvariation'
            setattr(macros, a, pn)
    upper = dict((k, mfna[k][0].upper() + mfna[k][1:]) for k in mfna)
    mac = mac[0].upper()+mac[1:]
    for a in [mac] + upper.keys():
        if not hasattr(macros, a):
            pn = pronoun(**upper)
            pn.hidden = 'pronounupper'
            setattr(macros, a, pn)
# First in the list wins
_pron('they', 'he', 'she', N='it')
_pron('them', 'him', 'her', N='it')
_pron('their', 'his', 'her', N='its')
_pron('theirs', 'his', 'hers', N='its')
_pron('themself', 'himself', 'herself', N='itself')
_pron('spouse', 'husband', 'wife', N='spouse', A='spouse')
_pron('offspring', 'son', 'daughter', N='child', A='child')
_pron('kid', 'boy', 'girl', N='kid', A='kid')
_pron('sibling', 'brother', 'sister', N='sibling', A='sibling')
_pron('parent', 'father', 'mother', N='parent', A='parent')
_pron('uncle', 'uncle', 'aunt')
_pron('nephew', 'nephew', 'niece')
_pron('human', 'man', 'woman', N='human', A='human')
_pron('gender', 'male', 'female', N='neuter', A='uncertain', S='other')

PRE=u'<<<pre/>>>'
SUF=u'<<<suf/>>>'
def parsename(name):
    gd = dict((k, '') for k in ('first', 'middle', 'last',
                                'prefix', 'suffix'))
    gd['full'] = name
    if SUF in name:
        name, gd['suffix'] = name.split(SUF, 1)
        gd['full'] = gd['full'].replace(SUF, ' ')
    elif ", " in name:
        name, gd['suffix'] = name.split(", ", 1)

    if PRE in name:
        gd['prefix'], name = name.split(PRE, 1)
        gd['full'] = gd['full'].replace(PRE, ' ')
    
    bits = name.split()
    assert len(bits) >= 1
    if len(bits) == 1:
        gd['first'] = bits[0]
    elif not gd['prefix'] and bits[0].endswith('.'):
        gd['prefix'] = bits[0]
        if len(bits) == 2:
            gd['last'] = bits[1]
        elif len(bits) == 3:
            gd['first'], gd['last'] = bits[1:]
        else:
            gd['first'] = bits[1]
            gd['last'] = bits[-1]
            gd['middle'] = ' '.join(bits[2:-1])
    else:
        if len(bits) == 2:
            gd['first'], gd['last'] = bits
        else:
            gd['first'] = bits[0]
            gd['last'] = bits[-1]
            gd['middle'] = ' '.join(bits[1:-1])

    gd['informal'] = gd['first'] or gd['last']
    
    gd['formal'] = gd['last'] or gd['first']
    if gd['prefix']:
        gd['formal'] = "%s %s" % (gd['prefix'], gd['formal'])
          
    return gd
    
def namepart(part, nameprop=u'name'):
    def np(argstr, content=None):
        if argstr.strip():
            namep = argstr.strip()
        else:
            namep = nameprop
        e = get_current_element()
        name = render_allow_override(e, namep,
                                     moverrides=dict(pre=PRE, suf=SUF))
        if name is None:
            raise WikiException("%s.%s is not defined for name parsing!"
                                % (e.ename,namep))
        #print >>sys.stderr, repr(name)
        namedict = parsename(name)
        yield Text(namedict[part])
    np.hidden = 'namepart'
    return np

macros.pre = atom(
    " ",
    doc="Marks the end of a title or prefix for name parsing.")
macros.suf = atom(
    " ",
    doc="Marks the start of an end title or suffix for name parsing.")
macros.first = namepart('first')
macros.middle = namepart('middle')
macros.last = namepart('last')
macros.full = namepart('full')
macros.formal = namepart('formal')
macros.informal = namepart('informal')
macros.player = leafprop(u'player')
macros.contact = leafprop(u'contact')
