from creoleparser import parse_args
from creoleparser.dialects import create_dialect, creole10_base, creole11_base
from creoleparser.core import Parser ,escape_char, esc_neg_look, fragmentize, ImplicitList

from creoleparser import text2html
from creoleparser.elements import InlineElement, WikiElement
import genshi.builder as bldr
import genshi.core
from genshi.filters import HTMLSanitizer
import re
import pygments
import pygments.lexers
import pygments.formatters
import pygments.util
import logging
import urllib, urlparse
from wakawaka.models import WikiPage
from mbed.favourites.models import add_usage
sanitizer = HTMLSanitizer()



class MbedWikiLink(WikiElement):

    """Used to match wiki links inside a link.

    The search scope for these is only inside links.

    >>> wiki_link = WikiLink('a','|',base_url='http://somewiki.org/',
    ...                      space_char='_',class_func=None, path_func=None)
    >>> mo = wiki_link.regexp.search(" Home Page |Home")
    >>> wiki_link.href(mo)
    'http://somewiki.org/Home_Page'
    >>> wiki_link.alias(mo,{},None)
    ['Home']

    """

    def __init__(self, tag, delimiter,
                 base_url,space_char,class_func,path_func,wikislug):
        super(MbedWikiLink,self).__init__(tag, '')
        self.delimiter = delimiter
        self.base_url = base_url
        self.space_char = space_char
        self.class_func = class_func
        self.path_func = path_func
        self.regexp = re.compile(self.re_string())
        self.wikislug = wikislug
    
    def re_string(self):
        optional_spaces = ' *'
        page_name = r'(\S+?( \S+?)*?)' #allows any number of single spaces
        alias = r'(' + re.escape(self.delimiter) + r' *(.*?))? *$'
        return '^' + optional_spaces + page_name + optional_spaces + \
               alias

    def page_name(self,mo):
        return mo.group(1).replace(' ',self.space_char)

    def href(self,mo):
        if self.path_func:
            the_path = self.path_func(self.page_name(mo))
        else:
            the_path = urllib.quote(self.page_name(mo).encode('utf-8'))
        return urlparse.urljoin(self.base_url, the_path)

    def _build(self,mo,element_store, environ):
        #find if the page exists
        if environ:
            if environ.has_key('wikislug'):
                page = WikiPage.objects.filter(slug=self.page_name(mo), wiki__slug=environ['wikislug'])
                if len(page):
                    add_usage(user=environ['user'], object=page[0]
                             , usedby=environ['object'], usetype='MENTION')
        
        return ''

    def alias(self,mo,element_store, environ):
        """Returns the string for the content of the Element."""
        if not mo.group(3):
            return mo.group(1)
        else:
            return fragmentize(mo.group(4),self.child_elements,element_store, environ)



def creole_mbed_base(macro_func=None, **kwargs):
    """Our version of creole, inherits from 11_base"""
    wikislug = kwargs.pop('wikislug')

    Creole11Base = creole11_base(macro_func=macro_func, **kwargs)
    class Base(Creole11Base):
        def __init__(self):
            super(Base, self).__init__()

        from creoleparser.elements import Image
        wiki_link = MbedWikiLink('a',delimiter = '|',
                              base_url='',
                              space_char="-",
                              class_func=None,
                              path_func=None, 
                              wikislug=wikislug)

    return Base    
 

class MbedMentionParser:
    def __init__(self, wikislug='', object='', user=''):
        self.wikislug = wikislug
        self.object= object
        self.user = user
        self.parser = Parser(dialect=create_dialect(creole_mbed_base, macro_func=macro_func, wikislug=wikislug), method='xhtml')

    def get_parser(self):
        return self.parser

    def parse(self, source):
        return self.parser(source, environ={'wikislug':self.wikislug, 'user':self.user, 'object':self.object})
    

def macro_func(macro_name, arg_string,body,isblock,environ):
    """Matches a macro call in the wikitext to a real macro function"""
    try:
        pos, kw = parse_args(arg_string)

        kw['macro_name'] = macro_name
        kw['environ'] = environ

        if macro_name == 'program':
            return macro_program_mention(body,*pos,**kw)

        if macro_name == 'library':
            return macro_program_mention(body,*pos, libmode=True, **kw)


    except Exception, e:
        raise e
        return '[An error occured while processing this macro]'





#=============== Macros

def macro_program_mention(body, *pos, **kw):
    """Link to a program, rendering some description and other info"""
    from urlparse import urlparse
    from django.core.urlresolvers import resolve
    from mbed.filepublisher.models import PublishedProject
    from django.shortcuts import get_object_or_404
    from django.contrib.auth.models import User
    from mbed.comlibs.templatetags.common_tags import render_mbed_time
    from mbed.comlibs.util import label_for_user
    from django.utils.safestring import mark_safe
    from genshi import HTML

    from django.conf import settings
    try:
        apimode = False
        latestmode = False
        progurl = urlparse(pos[0]).path

        if progurl.endswith('.html'):
            apimode = True
            docspath = '/'.join(progurl.split('/')[7:])
            #chop off api bit
            progurl = '/'.join(progurl.split('/')[:6])
            
        
        resolved = resolve(progurl)   
        #attempt to get db object of pub proj
        res = []

        if 'first' in resolved[2]:
            res = PublishedProject.all_objects.filter(name=resolved[2]['first'], is_latest=True, user=get_object_or_404(User, username=resolved[2]['username']))
            latestmode = True
        elif 'version' in resolved[2]:
                if resolved[2]['version'] == 'latest':
                    latestmode = True
                    res = PublishedProject.all_objects.filter(name=resolved[2]['name'], is_latest=True, user=get_object_or_404(User, username=resolved[2]['username']))
                else:
                    res = PublishedProject.all_objects.filter(hash=resolved[2]['version'], user=get_object_or_404(User, username=resolved[2]['username']))
             
        assert(len(res) == 1)
        published = res[0]

        logging.debug("Now recording mention for program %s"%published)
        add_usage(user=kw['environ']['user'], object=published, usedby=kw['environ']['object'], usetype='MENTION')

        

    except Exception, e:
        logging.exception(e)
   

    




















