import sys, urlparse, posixpath

from django.template import Library, TextNode, Node, Context, Template
from django.template import TemplateSyntaxError
from django.conf import settings

from rldjango.common import urls

register = Library()

def functionName():
    return sys._getframe(1).f_code.co_name

@register.simple_tag
def mediaUrl():
    """
    Returns the string contained in the setting MEDIA_URL.
    """
    try:
        from django.conf import settings
    except ImportError:
        return ''
    return settings.MEDIA_URL

@register.tag
def appAdminMediaUrl(parser, token):
    bits = token.contents.split()
    if len(bits) != 2:
        raise TemplateSyntaxError, "%r statement takes one argument" % functionName()
    relativeRef = bits[1]
    uriRef = urlparse.urljoin(settings.MCE_CONFIG_URL, relativeRef)
    return TextNode(uriRef)

@register.tag
def mceUrl(parser, token):
    # we use a single MCE installation for all apps
    if len(token.contents.split()) != 1:
        raise TemplateSyntaxError, "%r statement takes no arguments" % functionName()
    uriRef = settings.MCE_URL
    return TextNode(uriRef)

@register.tag
def py(parser, token):
    contents = token.contents
    ii = contents.find(' ')
    if ii < 0:
        raise TemplateSyntaxError, "%r tag takes no arguments" % contents
    tagName, pythonExpr= contents[:ii], contents[ii+1:]
    return EvalNode(pythonExpr)

class EvalNode(Node):
    def __init__(self, pythonExpr):
        self.pythonExpr = pythonExpr
    def render(self, context):
        try:
            return eval(self.pythonExpr, {}, context)
        except:
            t,v,tb=sys.exc_info()
            v = '%s\npythonExpr=%r' % (str(v),self.pythonExpr)
            raise t,t(v),tb

@register.tag
def pyexec(parser, token):
    contents = token.contents
    ii = contents.find(' ')
    if ii < 0:
        raise TemplateSyntaxError, "%r tag takes no arguments" % contents
    tagName, pythonStmt = contents[:ii], contents[ii+1:]
    return ExecNode(pythonStmt)

class ExecNode(Node):
    def __init__(self, pythonStmt):
        self.pythonStmt = pythonStmt
    def render(self, context):
        globs = {}
        try:
            exec self.pythonStmt in globs, context
        except:
            t,v,tb=sys.exc_info()
            v = '%s\npythonStmt=%r' % (str(v),self.pythonStmt)
            raise t,t(v),tb
        for name, value in globs.items():
            context[name] = value
        return ''

@register.tag('#')
def comment(parser, token):
    contents = token.contents
    ii = contents.find(' ')
    if ii < 0:
        raise TemplateSyntaxError, "%r tag takes no arguments" % contents
    tagName, junk = contents[:ii], contents[ii+1:]
    return TextNode('')

def getFormfieldErrors(form, formfield):
    """
    Return any errors in the formfield
    (Why can't django put the errors in a useful place?)
    """
    if form.error_dict.has_key( formfield.field_name ):
        return '<p class="error">'+', '.join(form.error_dict[ formfield.field_name ])+'</p>'
    else:
        return ''
getFormfieldErrors = register.simple_tag(getFormfieldErrors)


def recurse_tree(node, seq=False):
    """
    node.type: ("element" | "seq")
    node.occur: ("once" | "opt")
    none.name: (str | None)
    """
    s = ""
    if node is  None:
        return s
    if node.type == 'or':
        s = "%s | %s" % (recurse_tree(node.left), recurse_tree(node.right))
    elif node.type == 'seq':
        if seq:
            s = "%s, %s" % (recurse_tree(node.left, True), recurse_tree(node.right, True))
        else:
            s = "( %s %s )" % (recurse_tree(node.left, True), recurse_tree(node.right, True))
    elif node.type == "element":
        if node.occur == 'opt':
            s = " [<a href='#%s'>%s</a>] " % (node.name, node.name)
        else:
            s = " <a href='#%s'>%s</a> " % (node.name, node.name)
        if seq:
            s += ","
    if node.occur == 'plus':
        s += "+"
    return s

import django
if float(django.get_version()[0:3]) >= 1.3:
    @register.assignment_tag(takes_context=True)
    def rml(context):
        from os import makedirs
        from os.path import join, isdir
        fname = join(settings.MEDIA_ROOT, 'rlextra','rml.html')
        res = ''
        if True:
        #if not os.path.exists(fname):
            from lxml import etree
            from markdown import markdown
            from django.template.loader import get_template
            if not isdir(join(settings.MEDIA_ROOT, 'rlextra')):
                makedirs(join(settings.MEDIA_ROOT, 'rlextra'))
            dtd_fname = getattr(settings, 'RML_DTD_PATH', join(settings.ENVIRON_DIR,'rlextra','rml2pdf','rml.dtd'))
            
            dtd = etree.DTD(open(dtd_fname))
            t = get_template("dtd_node.html")
            for ele in sorted(dtd.elements(), key=lambda x: x.name):
                c = {
                    'name': ele.name,
                    'element': ele,
                }
                c['content'] = recurse_tree(ele.content)
                if ele.attributes():
                    c['attributes'] = sorted(
                            sorted(ele.attributes(), key=lambda x: x.name), 
                            key=lambda x: x.default, 
                            reverse=True)
                elif c.has_key('attributes'):
                    del c['attributes']
                res += t.render(Context(c))
            f = open(fname, 'w')
            res = markdown(res)
            f.write(res)
        else:    
            f = open(fname)
            res = f.read()
        f.close()
        return res
