from django import template
from django.template import Node, NodeList, TemplateSyntaxError

register = template.Library()

class MailtoNode(Node):
    '''
        Node for mailto tag
    '''    
    def __init__(self, nodelist, email, subject, cc_list, bcc_list):
        self.nodelist = nodelist
        self.email=template.Variable(email)
        
        self.subject_words=None
        if subject is not None:
            if subject[0] == subject[-1] and subject[0] in ('"', "'"):
                subject=subject[1:-1]
            self.subject_words=[template.Variable(subject_word[2:-2]) if subject_word[0:2] == "{{" and subject_word[-2:] == "}}" else subject_word for subject_word in subject.split(" ")]
            
        self.cc_list=None
        if cc_list is not None:
            if cc_list[0] == cc_list[-1] and cc_list[0] in ('"', "'"):
                self.cc_list=cc_list[1:-1]
            else:
                self.cc_list=template.Variable(cc_list)

        self.bcc_list=None
        if bcc_list is not None:
            if bcc_list[0] == bcc_list[-1] and bcc_list[0] in ('"', "'"):
                self.bcc_list=bcc_list[1:-1]
            else:
                self.bcc_list=template.Variable(bcc_list)

    def render(self, context):
        try:
            email=self.email.resolve(context)
        except:
            email=self.email
            
        additional='?'
        if self.subject_words is not None:
            subject_words_expanded=[]
            for word in self.subject_words:
                word_expanded=''
                try:
                    word_expanded = word.resolve(context)
                except: 
                    word_expanded = word
                # Mailto links sometimes truncates the URI if there is an ampersand in the string somewhere
                subject_words_expanded.append(str(word_expanded).replace('&amp;', '%26').replace('&','%26'))
            additional += 'subject=%s&' % " ".join(subject_words_expanded)
    
        if self.cc_list is not None:
            try:
                cc_list=self.cc_list.resolve(context)
                if isinstance(cc_list, list):
                    cc_list=",".join(cc_list)
            except:
                cc_list=self.cc_list
            additional += 'cc=%s&' % (cc_list)
            
        if self.bcc_list is not None:
            try:
                bcc_list=self.bcc_list.resolve(context)
                if isinstance(bcc_list, list):
                    bcc_list=",".join(bcc_list)
            except:
                bcc_list=self.bcc_list
            additional += 'bcc=%s&' % (bcc_list)
           
        nodelist_expanded=[]
        for node in self.nodelist:
            try:
                nodelist_expanded.append(node.render(context))
            except:
                nodelist_expanded.append(node)
        linktext=' '.join(nodelist_expanded)
            
        return '<a href="mailto:%s%s">%s</a>' % (email, additional[0:-1], linktext)

@register.tag
def mailto(parser, token):
    '''
        Custom template tag to create complete mailto links.
        
        Format:
        
        {% mailto email subject comma_separated_cc_list comma_separated_bcc_list %}link content{% endmailto %}
        
        Where:  email is the recipient (only required field; string or context variable)
                subject is the subject for the email (optional; string containing context variables with no {{}}.)
                cc is the comma separated list of carbon copied (optional; will also accept a variable containing a string or python list)
                bcc is the comma separated list of blind carbon copied (optional; will also accept a variable containing a string or a python list)
        
        Examples: 
            {% mailto 'blah@blah.com' 'subject line' 'nancy@blah.com, joe@blah.com' 'secret@blah.com' %}link text{% endmailto %}
        Produces:
            <a href="mailto:blah@blah.com?subject=subject line&cc=nancy@blah.com, joe@blah.com&bcc=secret@blah.com">link text</a>
    
        Examples: 
            {% mailto context.var.email 'subject for user.get_full_name' context.var.cc 'secret@blah.com' %}link text{% endmailto %}
            Where context.var.email has joedoe@doeloop.com, context.var.cc has janedoe@doeloop.com, and current user is jimmy
        Produces:
            <a href="mailto:joedoe@doeloop.com?subject=subject for jimmy&cc=janedoe@doeloop.com&bcc=secret@blah.com">link text</a>
    '''
    tokenlist = token.split_contents()
    if len(tokenlist) < 2:
        raise TemplateSyntaxError("'%s' takes at least one argument"
                                  " (the email recipient)" % tokenlist[0])
    
    email=tokenlist[1]
    subject=None
    if len(tokenlist) >= 3:
        subject = tokenlist[2]
    cc_list=None
    if len(tokenlist) >= 4:
        cc_list=tokenlist[3]
    bcc_list=None
    if len(tokenlist) == 5:
        bcc_list=tokenlist[4]
    
    nodelist = parser.parse(('endmailto',))
    parser.delete_first_token()
    
    return MailtoNode(nodelist, email, subject, cc_list, bcc_list)