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

dependencies = []

class TestScore:
    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.open('table', attr={'class':'quizscore'})
        html+=self.formatter.open('tr', attr={'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.open('td')
        html+=self.formatter.text(_('Question'))
        html+=self.formatter.close('td')
        for question in questions:
            html+=self.formatter.open('td')
                html+=self.formatter.text(question)
                html+=self.formatter.close('td')
        html+=self.formatter.open('td')
        html+=self.formatter.text(_('Total'))
        html+=self.formatter.close('td')
        html+=self.formatter.close('tr')
        l = [x for x in user_answers.iteritems()];
        l.sort();
        for user, answers in l:
            if user:
                row = ''
                row+=self.formatter.open('td')
                row+=self.formatter.pagelink(None, pagename=user, text=self.clean_name(user))
                row+=self.formatter.close('td')
                sum = 0;
                small_sum = 0;
                for question in questions:
                    row+=self.formatter.open('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.open('small')
                                row+=self.formatter.text(' (')
                                row+=self.formatter.text(small)
                                row+=self.formatter.text(')')
                                row+=self.formatter.close('small')
                                small_sum += small
                    else:
                        row+=self.formatter.text('-')
                    row+=self.formatter.close('td')
                row+=self.formatter.open('td')
                row+=self.formatter.text(sum)
                row+=self.formatter.open('small')
                row+=self.formatter.text(' (')
                row+=self.formatter.text(small_sum)
                row+=self.formatter.text(')')
                row+=self.formatter.close('small')
                row+=self.formatter.close('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.open('tr', attr={'class':'score%s'%score})
                html+=row
                html+=self.formatter.close('tr')
        html+=self.formatter.close('table')
        return html



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