import re
from MoinMoin import config, wikiutil
from MoinMoin.Page import Page

dependencies = []

class QuizScore:
    def __init__(self, macro, args):
        self.macro = macro
        self.pagename = macro.request.page.page_name
        self.request = macro.request
        self.formatter = macro.formatter
        self.args = args
        self.arglist = args.split(',')
	self.counters = {}
        if len(self.arglist)<1:
            self.base_page_name = self.pagename;
        else:
            self.base_page_name = self.arglist[0]
        if len(self.arglist)<2:
            self.answers_page_name = macro.request.user.name;
        else:
            self.answers_page_name = self.arglist[1]

    def get_answer_pages(self):
        isgroup = re.compile(self.request.cfg.page_group_regex, re.UNICODE).search
        pages = self.request.rootpage.getPageList(user='', exists='')
        matches = []
        for name in pages:
	    p = Page(self.request, name)
            if name.startswith(self.base_page_name+'/') and p.exists() and self.request.user.may.read(name):
		    if not isgroup(name): 
			matches.append(name)
        return matches
    
    def get_answers(self, name):
        p = Page(self.request, name)
        text = p.get_raw_body()
	if not text:
		return {}
        answers = {}
        question = ''
        answers[''] = set()
        regex = re.compile(r'^\s*(?P<question>.*)::|^\s*\*\s*(?P<answer>.*)|^\#.*$|^\s*$')
        for line in text.split('\n'):
            m = regex.match(line)
            if m:
                keys = m.groupdict()
                if keys.has_key('question') and keys['question']:
                    question = keys['question'].strip()
                    if not answers.has_key(question) and question!='counter':
                        answers[question] = set()
                elif keys.has_key('answer') and keys['answer']:
		    answer = keys['answer'].strip()
		    if question == 'counter' and name==self.base_page_name+'/'+self.answers_page_name:
			    if not self.counters.has_key(answer):
				    self.counters[answer] = 0
			    self.counters[answer]+=1
		    elif question!='counter':
			    answers[question].add(answer)
        return answers
    
    def clean_name(self,name):
        return name[len(self.base_page_name):]

    def score_answers(self, answer1, answer2, question):
	equal = answer1==answer2
	if self.counters.has_key(question):
		score = self.counters[question] - len(answer1-answer2) - len(answer2-answer1)
	else:
		score = -1 
        return equal, score


    def execute(self):
        _ = self.request.getText
        answer_pages = self.get_answer_pages()
        user_answers = {}
        for page_name in answer_pages:
            user_answers[page_name] = self.get_answers(page_name)
        html = self.formatter.rawHTML('<table class="quizscore">')
        html+=self.formatter.rawHTML('<tr class="head">')
	if not user_answers.has_key(self.base_page_name+'/'+self.answers_page_name):
		return self.formatter.text(_(u'Score not available yet.'))
        correct = user_answers[self.base_page_name+'/'+self.answers_page_name]
        questions = [x for (x,y) in correct.iteritems()]
        questions.remove('')
        questions.sort()
        html+=self.formatter.rawHTML('<td>')
        html+=self.formatter.text(_('Question'))
        html+=self.formatter.rawHTML('</td>')
        for question in questions:
                html+=self.formatter.rawHTML('<td>')
                html+=self.formatter.text(question)
                html+=self.formatter.rawHTML('</td>')
        html+=self.formatter.rawHTML('<td>')
        html+=self.formatter.text(_('Total'))
        html+=self.formatter.rawHTML('</td>')
        html+=self.formatter.rawHTML('</tr>')
        l = [x for x in user_answers.iteritems()];
        l.sort();
        for user, answers in l:
            if user:
                row = ''
                row+=self.formatter.rawHTML('<td>')
                row+=self.formatter.pagelink(None, pagename=user, text=self.clean_name(user))
                row+=self.formatter.rawHTML('</td>')
                sum = 0;
		small_sum = 0;
                for question in questions:
                    row+=self.formatter.rawHTML('<td>')
                    if answers.has_key(question):
                        ok,small = self.score_answers(correct[question], answers[question], question)
			if ok:
                            row+=self.formatter.text('1')
                            sum += 1
                        else:
                            row+=self.formatter.text('0')
			if small>=0:
				row+=self.formatter.rawHTML('<small>')
				row+=self.formatter.text(' (')
				row+=self.formatter.text(str(small))
				row+=self.formatter.text(')')
				row+=self.formatter.rawHTML('</small>')
				small_sum += small
                    else:
                        row+=self.formatter.text('-')
                    row+=self.formatter.rawHTML('</td>')
                row+=self.formatter.rawHTML('<td>')
                row+=self.formatter.text(str(sum))
		row+=self.formatter.rawHTML('<small>')
                row+=self.formatter.text(' (')
                row+=self.formatter.text(str(small_sum))
                row+=self.formatter.text(')')
		row+=self.formatter.rawHTML('</small>')
                row+=self.formatter.rawHTML('</td>')
		if sum == len(questions):
			score='perfect'
		elif sum == 0:
			score='failed'
		elif user==self.base_page_name+'/'+self.answers_page_name:
			score='author'
		else:
			score = 'normal'
                html+=self.formatter.rawHTML('<tr class="score%s" >' % score)
                html+=row
                html+=self.formatter.rawHTML('</tr>')
        html+=self.formatter.rawHTML('</table>')
        return html
                
            

# Glue for MoinMoin 1.3.5
def execute(macro, args):
    return QuizScore(macro, args).execute()
