# coding: utf-8
'''
Created on 27.07.2015
☦☦☦☦☦☦☦☦☦☦☦☦☦☦☦☦☦☦☦☦☦☦☦☦☦
@author: tr0glo)|(I╠╣
☦☦☦☦☦☦☦☦☦☦☦☦☦☦☦☦☦☦☦☦☦☦☦☦☦
'''
from java.util import Date
from time import time
import json
from uuid import uuid4  
from ru.curs.celesta.showcase.utils import XMLJSONConverter
from qt.functions import completeTest, getImageById,\
    getAttributeValue, getQuestionImg, getTimeJs, getVariantParams,\
    getQuestionFields, getTestingAlgorithm, getVariantAnswerParams
try:
    from ru.curs.showcase.core.jython import JythonDTO
    from ru.curs.showcase.core.jython import JythonDownloadResult
except:
    from ru.curs.celesta.showcase import JythonDTO

from qt.functions import getShowCorrectAnswerPermission
from qt._qt_orm import QtiVariantQuestionCursor, QtiVariantAnswerCursor, \
    QtiDestructorCursor, QtiVariantDestructorCursor, QtiVariantDestructorAnswerCursor,\
    QtiResourceCursor  , QtiVariantParamsCursor

def cardData(context, main=None, add=None, filterinfo=None, session=None, elementId=None):
    u'''Карточка вопроса с одиночным выбором и для вопроса с множественным выбором. '''
    begin = time()
    sessionContext = json.loads(session)

    variantQuestionId = main

    variant_params = getVariantParams(context, variantQuestionId)  
    variantId = variant_params['variant_id']
    
    print 'start', time() - begin        
    #Проверка на то,  нужно ли отображать правильный ответ
    correctAnswerFlag = getShowCorrectAnswerPermission(context, sessionContext, variantId)

    print 'countquest', time() - begin
    testingAlgorithm = getTestingAlgorithm(context, variantId)
        
    print 'header', time() - begin
       
    variant_answer_params = getVariantAnswerParams(context, variantId)   
    testingStatus = variant_answer_params['testingStatus']
    
    optionList = []
    resultList = []
    letter = ord('A')
    print 'prequest', time() - begin    
    
    QtiVariantDestructor = QtiVariantDestructorCursor(context)
    QtiVariantDestructor.setRange('VariantQuestionID',variantQuestionId)    
    QtiVariantDestructor.orderBy('VariantDestructorID')
    vd_items = {}
    for QtiVariantDestructor in QtiVariantDestructor.iterate():
        vd_items[QtiVariantDestructor.VariantDestructorID] = QtiVariantDestructor.DestructorID
    QtiVariantDestructor.close()
    
    QtiDestructor = QtiDestructorCursor(context)
    QtiVariantDestructorAnswer = QtiVariantDestructorAnswerCursor(context)

    for vd_id, destructor_id in vd_items.items():     
        QtiDestructor.get(destructor_id)
#         variantDestructorId = QtiVariantDestructor.VariantDestructorID
        destructorHtml = QtiDestructor.DestructorHtml if QtiDestructor.DestructorHtml is not None else ''
        destructorHtml2 = QtiDestructor.DestructorHtml2 if QtiDestructor.DestructorHtml2 is not None else ''
        if QtiDestructor.DestructorImg:
            QtiResource = QtiResourceCursor(context)
            destructorImg =  getImageById(QtiResource, QtiDestructor.DestructorImg)
            QtiResource.close()
        else:
            destructorImg = ''
        correctFlag = False
        if correctAnswerFlag and QtiDestructor.IsTrue:
            correctFlag = True        
        optionList.append({"id": vd_id,
                            "letter": chr(letter),
                            "destructorHTML": destructorHtml + destructorImg + destructorHtml2,
                            "isTrue": 'true' if correctFlag else 'false'})
        letter += 1
        checked = '1_' if testingStatus != '0' else '0_'
        
        #Проверям выбирал ли текущий вариант пользователь, когда в предыдущий раз отвечал на этот вопрос
        QtiVariantDestructorAnswer.setRange('VariantDestructorID', vd_id)
        if QtiVariantDestructorAnswer.tryFirst():
            if QtiVariantDestructorAnswer.IsTrue:
                checked += '1'
            else:
                checked += '0'
        else:
            checked += '0'
        resultList.append({"id": vd_id, "checked": checked})

    QtiDestructor.close()
    QtiVariantDestructorAnswer.close()
    
    print 'calcList', time() - begin   
    js = getTimeJs(Date(), variant_answer_params['timeEnd'])
    
    QtiVariantParams = QtiVariantParamsCursor(context)
    skipQuestions = getAttributeValue(QtiVariantParams, variantId, 'SkipQuestions')
    changeAnswer = getAttributeValue(QtiVariantParams, variantId, 'ChangeAnswer')
    QtiVariantParams.close()
    
    fields = getQuestionFields(context, variant_params['question_id'])    
    questionImg = getQuestionImg(context, fields['img_id'])    
        
    xformsdata = {"schema": {
                    "@xmlns": "",
                    "description": {
                        "testingAlgorithm": testingAlgorithm,
                        "js": js,
                        "questionHeader": u'Вопрос %s из %s'%(variant_params['question_number'], variant_params['question_count']),
                        "questionType": '1',
                        "testingStatus": testingStatus,
                        "showCorrect": 'true' if correctAnswerFlag else 'false',
                        "captchaText":'',
                        "images": questionImg,
                        'variantId': variantId,
                        "skipQuestions": skipQuestions,
                        "changeAnswer": changeAnswer,
                        "hasAnswer": variant_params['has_answer'],
                        "question": {
                            "@number": variant_params['question_number'],
                            "@isLastQuestion":'1' if variant_params['next_variant_question_id'] == 'ID_FINISH' else '0',
                            "@timeout": variant_answer_params['timeout'],
                            "#text": fields['question_html']},#  + questionImg + questionHtml2 + ']]>'
                            "options": {"option": optionList}},
                        "result": {"option": resultList}}}
    #Переходы к следующему и предыдущему вопросам, завершению тестирования и списку вопросов
    xformssettings = {"properties": {
                        "event": [
                            {"@name":"single_click",
                             "@linkId": "1",
                             "action": {
                                "#sorted": [
                                    {"navigator": {"@element": variant_params['prev_variant_question_id']}}]}},
                            {"@name":"single_click",
                             "@linkId": "2",
                             "action": {
                                "#sorted": [
                                    {"navigator": {"@element": variant_params['next_variant_question_id']}}]}},
                            {"@name":"single_click",
                             "@linkId": "3",
                             "action": {
                                "#sorted": [
                                    {"navigator": {"@element": "ID_FINISH"}}]}},
                            {"@name":"single_click",
                             "@linkId": "4",
                             "action": {
                                "#sorted": [
                                    {"navigator": {"@element": "ID_CONTENTS"}}]}}]}}
    #print XMLJSONConverter(input=xformsdata).parse(), XMLJSONConverter(input=xformssettings).parse()
    data = XMLJSONConverter.jsonToXml(json.dumps(xformsdata))
    data = data.replace('&nbsp;','&amp;nbsp;')
    settings = XMLJSONConverter.jsonToXml(json.dumps(xformssettings))

    print 'finish', time() - begin
    return JythonDTO(data, settings)


def cardDataSave(context, main=None, add=None, filterinfo=None, session=None, elementId=None, xformsdata=None):
    u'''Процедура сохранения ответа на вопрос. Для всех типов вопросов используется общая процедура сохранения'''
    ip = json.loads(session)['sessioncontext']['ip']
    data_json = json.loads(xformsdata)['schema']
    questionType = int(data_json['description']['questionType'])

    variantId = data_json['description']['variantId']
    
    variantQuestionId = main
    question_id = None
    
    QtiVariantQuestion = QtiVariantQuestionCursor(context)    
    if QtiVariantQuestion.tryGet(variantQuestionId):
        question_id = QtiVariantQuestion.QuestionID
    QtiVariantQuestion.close()    
   
    now = Date()
    QtiVariantAnswer = QtiVariantAnswerCursor(context)
    QtiVariantAnswer.setRange('VariantID',variantId)
    QtiVariantAnswer.first()
    
    timeEnd = QtiVariantAnswer.TimeFinish if QtiVariantAnswer.TimeFinish is not None else QtiVariantAnswer.TimeEnd
    QtiVariantAnswer.close()
    
    timeout = True if now > timeEnd else False
    #Если время тестирования завершилось, то ответ на текущий вопрос не сохраняем и завешаем тестирование
    if timeout:
        completeTest(context, variantId)
        return
    
    #Удаляем предыдущий ответ на вопрос
    QtiVariantDestructor = QtiVariantDestructorCursor(context)
    QtiVariantDestructor.setRange('VariantQuestionID', variantQuestionId)
    QtiVariantDestructorAnswer = QtiVariantDestructorAnswerCursor(context)
    for QtiVariantDestructor in QtiVariantDestructor.iterate():
        QtiVariantDestructorAnswer.setRange('VariantDestructorID', QtiVariantDestructor.VariantDestructorID)
        QtiVariantDestructorAnswer.deleteAll()
    QtiVariantDestructor.close()
    
    data = data_json['result']
    optionsList = []
    checkFlag = True
    
    if questionType == 1 or questionType == 2:
        #Для вопрсов с одиночным и множественным выбором в ответы пишутся идентификаторы выбранных вариантов
        optionsListTemp = data['option']
        
        if not isinstance(optionsListTemp,list):
            optionsListTemp = [optionsListTemp]
        for option in optionsListTemp:
            if option['checked'] == '0_1':
                optionsList.append(option['id'])
#                 QtiVariantDestructor.get(option['id'])
                QtiVariantDestructorAnswer.VariantDestructorAnswerID = unicode(uuid4())
                QtiVariantDestructorAnswer.VariantDestructorID = option['id']
                QtiVariantDestructorAnswer.IsTrue = True
                QtiVariantDestructorAnswer.AnswerIP = ip
                QtiVariantDestructorAnswer.insert()

        if optionsList:
            QtiDestructor = QtiDestructorCursor(context)
            QtiDestructor.setRange('QuestionID', question_id)
            QtiDestructor.setRange('IsTrue', True)
            answerList = []
            # Формируе список правильных вариантов отвтов
            for QtiDestructor in QtiDestructor.iterate():
                answerList.append(QtiDestructor.DestructorID)
            QtiDestructor.close()
            
            QtiVariantDestructor = QtiVariantDestructorCursor(context)
            QtiVariantDestructor.setRange('VariantQuestionID', variantQuestionId)
            for QtiVariantDestructor in QtiVariantDestructor.iterate():
                if QtiVariantDestructor.VariantDestructorID in optionsList:
                    if QtiVariantDestructor.DestructorID not in answerList:
                        checkFlag = False
                    else:
                        answerList.remove(QtiVariantDestructor.DestructorID)                    
            QtiVariantDestructor.close()

            if answerList != []:
                checkFlag = False

    elif questionType == 3:
        #Для текстового вопрос записывается текст ответ в поле DestructorText
        if data['option']['answer']:
            optionsList = [data['option']['answer']]
        variantDestructorId = data['option']['@id']
        QtiVariantDestructorAnswer.VariantDestructorAnswerID = unicode(uuid4())
        QtiVariantDestructorAnswer.VariantDestructorID = variantDestructorId
        QtiVariantDestructorAnswer.DestructorText = data['option']['answer']
        QtiVariantDestructorAnswer.IsTrue = True
        QtiVariantDestructorAnswer.AnswerIP = ip
        QtiVariantDestructorAnswer.insert()
        
        if optionsList:
            QtiDestructor = QtiDestructorCursor(context)
            QtiDestructor.setRange('QuestionID', question_id)
            if QtiDestructor.tryFirst():
                if optionsList[0] != QtiDestructor.DestructorHtml:
                    checkFlag = False
            QtiDestructor.close()
        
    elif questionType == 4 or questionType == 6:
        #Для соответствия и классификации в DestructorId пишутся какой вариант из правого столбца был выбран
        if 'option2' in data:
            optionsList = data['option2']
            if not isinstance(optionsList,list):
                optionsList = [optionsList]
            for option in optionsList:
                QtiVariantDestructorAnswer.VariantDestructorAnswerID = unicode(uuid4())
                QtiVariantDestructorAnswer.VariantDestructorID = option['@VariantDestructorID']
                QtiVariantDestructorAnswer.DestructorID = option['@DestructorID']
                QtiVariantDestructorAnswer.IsTrue = True
                QtiVariantDestructorAnswer.AnswerIP = ip
                QtiVariantDestructorAnswer.insert()
                
            if optionsList:
                optionDict = dict((str(p['@VariantDestructorID']), p['@DestructorID']) for p in optionsList)
                QtiVariantDestructor = QtiVariantDestructorCursor(context)
                QtiVariantDestructor.setRange('VariantQuestionID', variantQuestionId)
                for QtiVariantDestructor in QtiVariantDestructor.iterate():
                    if optionDict[QtiVariantDestructor.VariantDestructorID] != QtiVariantDestructor.DestructorID:
                        checkFlag = False
                QtiVariantDestructor.close()
                
    elif questionType == 5:
        #Для сортировки в DestructorText пишется порядковый номер варианта
        if 'option2' in data:
            optionsList = data['option2']
            if not isinstance(optionsList,list):
                optionsList = [optionsList]
            for option in optionsList:
                QtiVariantDestructorAnswer.VariantDestructorAnswerID = unicode(uuid4())
                QtiVariantDestructorAnswer.VariantDestructorID = option['@id']
                QtiVariantDestructorAnswer.DestructorText = option['@text']
                QtiVariantDestructorAnswer.IsTrue = True
                QtiVariantDestructorAnswer.AnswerIP = ip
                QtiVariantDestructorAnswer.insert()
            if optionsList:
                optionDict = dict((str(p['@id']), p['@text']) for p in optionsList)
                QtiDestructor = QtiDestructorCursor(context)
                QtiVariantDestructor = QtiVariantDestructorCursor(context)
                QtiVariantDestructor.setRange('VariantQuestionID', variantQuestionId)                
                for QtiVariantDestructor in QtiVariantDestructor.iterate():
                    QtiDestructor.get(QtiVariantDestructor.DestructorID)
                    if optionDict.get(QtiVariantDestructor.VariantDestructorID):
                        if int(QtiDestructor.DestructorOrder) != int(optionDict[QtiVariantDestructor.VariantDestructorID]):
                            checkFlag = False
                    else:
                        checkFlag = False
                QtiDestructor.close()
                QtiVariantDestructor.close()

    QtiVariantDestructorAnswer.close()
    
    QtiVariantQuestion = QtiVariantQuestionCursor(context)    
    if QtiVariantQuestion.tryGet(variantQuestionId):
        QtiVariantQuestion.HasAnswer = True if optionsList else False
        QtiVariantQuestion.CorrectAnswer = checkFlag and QtiVariantQuestion.HasAnswer
        QtiVariantQuestion.update()
    QtiVariantQuestion.close()

    