# coding: utf-8
'''
Created on 06.03.2015

@author: v.popov
'''
import codecs
import datetime
import random
import tempfile
from bs4 import BeautifulSoup
from java.util import ArrayList
from java.util.zip import *
from java.io import FileInputStream, FileOutputStream
import json
from uuid import uuid4
import uuid
from zipfile import ZipFile
from author._author_orm import serviceCatalogCursor
from qt._qt_orm import QtiPackageCursor, QtiThemeCursor, \
    QtiPackageAttributeCursor, QtiQuestionCursor, QtiDestructorCursor, \
    listAttributeContentCursor, ContentCursor, Content_AttributeValueCursor
from common.grainssettings import SettingsManager
from ru.curs.celesta.showcase.utils import XMLJSONConverter
from qt.functions import setAccessPermission, getGlobalAttributeValue


try:
    from ru.curs.showcase.core.jython import JythonDTO
    from ru.curs.showcase.core.selector import ResultSelectorData
    from ru.beta2.extra.gwt.ui.selector.api import DataRecord
    from ru.curs.showcase.app.api import UserMessage, MessageType
    from ru.curs.showcase.core.jython import JythonDownloadResult
except:
    from ru.curs.celesta.showcase import JythonDTO, ResultSelectorData, DataRecord, UserMessage, MessageType




def cardData(context, main=None, add=None, filterinfo=None, session=None, elementId=None):
    u'''Данные для карточки.'''

    session = json.loads(session)
    package_id = session['sessioncontext']['related']['gridContext']['currentRecordId']
    variant_id = unicode(uuid.uuid4())


    # Структура данных
    xformsdata = {  
        'schema':{  
            '@xmlns':'',
            'data':{  
                    'number':'',
                    'variant_id': variant_id,
                    'package_id': package_id
                    
            }
        }
    }



    # Первоначальная xformssettings
    xformssettings = {  
        'properties': {  
            'event': [  
                {  
                    '@name': 'single_click',
                    '@linkId': '1',
                    'action': {"#sorted":
                               [
                                    {'main_context': 'current'},
                            
                                    {'datapanel': 
                                        {  
                                            '@type': 'current',
                                            '@tab': 'current',
                                            'element': [  
                                                {  
                                                    '@id': elementId,
                                                    'add_context': 'hide'
                                                }
                
                                            ]
                                         }
                                     }
                                ]
                               }
                    },
                                    {  
                    '@name': 'single_click',
                    '@linkId': '2',
                    'action': {
                               "@show_in":"MODAL_WINDOW",
                               "#sorted":
                               [
                                    {'main_context': 'current'},
                            
                                    {'datapanel': 
                                        {  '@type': 'current',
                                            '@tab': 'current',
                                            'element': [  
                                                {  
                                                    '@id': 'testBtzCard',
                                                    'add_context': add
                                                }
                
                                            ]
                                         }
                                     }
                                ]
                               }
                    }
                ]
        }
    }
    
    return JythonDTO(XMLJSONConverter.jsonToXml(json.dumps(xformsdata)), XMLJSONConverter.jsonToXml(json.dumps(xformssettings)))


def cardSave(context, main=None, add=None, filterinfo=None, session=None, elementId=None, xformsdata=None):
    u'''Сохранение карточки. '''

    session = json.loads(session)
    data = json.loads(xformsdata)
#     package_id = add['package_id']
    variant_id = data['schema']['data']['variant_id']
    sid = session['sessioncontext']['sid']
    mode = data['schema']['data']['mode_id']
    setAccessPermission(context, sid, mode, variant_id)


def downloadVariantCard(context, main=None, add=None, filterInfo=None, session=None, elementId=None, xformsdata=None):
    u"""Функция выгрузки файлов БТЗ с сервера"""
    
    data_dict = json.loads(xformsdata)
    session = json.loads(session)
    gridContext = session['sessioncontext']['related']['gridContext']
    
    package_id = gridContext['currentRecordId']
    variant_number = int(data_dict['schema']['data']['number'])
    

    package = QtiPackageCursor(context)
    QtiTheme = QtiThemeCursor(context)
    QtiQuestion = QtiQuestionCursor(context)
    QtiDestructor = QtiDestructorCursor(context)
    content = ContentCursor(context)
    contentAttr = Content_AttributeValueCursor(context)
    listAttributeContent = listAttributeContentCursor(context)
    
    try:
        noRandom = getGlobalAttributeValue(content, contentAttr, listAttributeContent, package_id, 'NoRandom')
        quantityQuest = getGlobalAttributeValue(content, contentAttr, listAttributeContent, package_id, 'QuantityQuestions')
    except:
        return context.error(u'Не заданы настройки тестов')
     

    result = ZipFile("result.zip", "w")
  
#     out = ZipOutputStream(FileOutputStream('result.zip'))
    
    for variant_num in range(variant_number):
#         print '----------',i,'---------'
        html_variant = [codecs.BOM_UTF8]
        html_answers = [codecs.BOM_UTF8]
        html_correct = [codecs.BOM_UTF8]
        html_variant.append(str('<html><head><title>Вариант №%d</title><body><center><h3>Вариант №%d</h3></center>'%(variant_num+1,variant_num+1)))
        html_answers.append(str('<html><head><title>Ответы №%d</title><body><h3>Вариант №%d</h3><table border="1" cellpadding="7" cellspacing="0" cols="2" width="600">'%(variant_num+1,variant_num+1)))
        html_correct.append(str('<html><head><title>Правильные ответы №%d</title><body><h3>Вариант №%d</h3><table border="1" cellpadding="7" cellspacing="0" cols="2" width="600">'%(variant_num+1,variant_num+1)))
        themeDict = dict()
        themeList = list()
        questionDict = dict()
        count = 0
        QtiTheme.orderBy('ThemeOrder')
        QtiTheme.setRange('PackageID', package_id)
        # Формируется список тем и словарь списков вопросов по темам. Темы и вопросы упорядочены по соответствующим табличным полям.
        for theme in QtiTheme.iterate():
            QtiQuestion.setRange('ThemeID', theme.ThemeID)
            themeDict[theme.ThemeID] = QtiQuestion.count()
            themeList.append(theme.ThemeID)
            count += QtiQuestion.count()
            questionDict[theme.ThemeID] = list()
            QtiQuestion.orderBy('QuestionOrder')
            for question in QtiQuestion.iterate():
                questionDict[theme.ThemeID].append(question.QuestionID)
        # Если количество вопросов не определено, то берутся все доступные вопросы.
        if quantityQuest is None or quantityQuest == '':    
            quantityQuest = count
        if noRandom is None or noRandom == '':
            noRandom = '1'
        QtiTheme.orderBy('ThemeOrder')
        remainQuest = min(int(quantityQuest), count)
        number = 1
        while remainQuest > 0:
        #         raise Exception(remainQuest,len(themeList),themeList)
            print remainQuest, len(themeList), themeList
            # Пытаемя равномерно распределить вопросы по темам
            questCountInt = remainQuest / len(themeList)
            print questCountInt
            k = len(themeList)
            # Если нужно вопросов меньше, чем тем, то случайным образом выбираем темы.
            if questCountInt == 0:
                k = remainQuest
                questCountInt = 1
            print questCountInt
            deleteThemeList = list()
            # В режиме отладки выбиратся все вопросы по порядку
                # Перебираем в случайном порядке темы
            for theme in random.sample(themeList, k):
                print theme, len(questionDict[theme])
                # Если в текущей теме осталось вопросов меньше чем нужно взять, то берём все доступные вопросы и помечаем тему для удаления из списка доступных тем
                if len(questionDict[theme]) < questCountInt:
                    remainQuest -= len(questionDict[theme])
                    deleteThemeList.append(theme)
                    for question in questionDict[theme]:
                        addQuestion(html_variant,html_answers,html_correct,question,QtiQuestion,QtiDestructor,number)
                        number += 1
                else:
                    # Если вопросов в теме ровно столько, скольки и нужно, то помечаем тему для удаления из списка доступных тем
                    if len(questionDict[theme]) == questCountInt:
                        deleteThemeList.append(theme)
                    deleteQuestionList = list()
                    remainQuest -= questCountInt
                    # Выбор вопросов по порядку
                    if noRandom == '1':                  
                        for i in range(questCountInt):
                            deleteQuestionList.append(questionDict[theme][i])
                            addQuestion(html_variant,html_answers,html_correct,questionDict[theme][i],QtiQuestion,QtiDestructor,number)
                            
                            number += 1
                    # Выбор случайных вопросов
                    elif noRandom == '0':
                        questions = random.sample(questionDict[theme], questCountInt)
                        for question in questions:
                            deleteQuestionList.append(question)
                            addQuestion(html_variant,html_answers,html_correct,question,QtiQuestion,QtiDestructor,number)
                            number += 1
                    # Удаляем выбранные вопросы из списка доступных вопросов по теме.
                    for question in deleteQuestionList:
                        questionDict[theme].remove(question)
            # Удаялем темы, в которых нет вопросов из списка доступных тем.
            for theme in deleteThemeList:
                themeList.remove(theme)
#         result.writestr('html_%d.html'%(i+1),'<html><head><title>Вариант №%d</title><body>'%(i+1))
        html_variant.append(str('</body></html>'))
        html_answers.append(str('</table></body></html>'))
        html_correct.append(str('</table></body></html>'))

   
        result.writestr('html_%d.html'%(variant_num+1),''.join(html_variant))
        result.writestr('answers_%d.html'%(variant_num+1),''.join(html_answers))
        result.writestr('correct_%d.html'%(variant_num+1),''.join(html_correct))
    result.close()

    u"""Создание входного потока данных""" 
    report = FileInputStream('result.zip')
    
    u"""Возврат переконвертированного файла""" 
    return JythonDownloadResult(report, u'test.zip')

    
def addQuestion(html_variant,html_answers,html_correct,question_id,qti_question,qti_destructor,number):
    qti_question.get(question_id)
    question_type = qti_question.QuestionType
    html_variant.append(str('<table border="1" width="1000" cellpadding="7" cellspacing="0"><tr><td width="20">%s</td><td width="980">%s</td><tr>'%(str(number),str(qti_question.QuestionHtml.replace('&lt;','<').replace('&gt;','>')))))
    qti_destructor.setRange('QuestionID',question_id)
    destructorList = []
    destructorListAnswers = []
    destructorTextList = []
    destructorTextSet = set()
    for destructor in qti_destructor.iterate():
        destructorList.append(destructor.DestructorID)
        destructorListAnswers.append(destructor.DestructorID)
        if question_type != 3:
            if destructor.AnswerText not in destructorTextSet:
                destructorTextList.append(destructor.AnswerText)
                destructorTextSet.add(destructor.AnswerText)
        else:
            destructorTextList.append(destructor.DestructorHtml)
    random.shuffle(destructorList)
    random.shuffle(destructorTextList)
    num = 0
    correctList = ['' for j in xrange(len(destructorList))]
    answerList = []
    if question_type != 3:
        
        letter = ord('A')
        for destructorId in destructorList:
            qti_destructor.get(destructorId)
            if question_type in (1,2,3,5):
                html_variant.append(str('<tr><td width="5">%s</td><td width="99%s">%s</td><tr>'%(chr(letter),'%',str(qti_destructor.DestructorHtml.replace('&lt;','<').replace('&gt;','>')))))
                if (question_type == 2 or question_type == 1) and qti_destructor.IsTrue:
                    correctList[num] = chr(letter)
                if (question_type == 5):
                    correctList[qti_destructor.DestructorOrder-1] = chr(letter)
            elif (question_type == 4 or question_type == 6):
                answerList.append('%s-______'%chr(letter))
                correctList[num] = '%s-%d'%(chr(letter),destructorTextList.index(qti_destructor.AnswerText)+1)
                if num < len(destructorTextList):
                    html_variant.append(str('<tr><td width="5%s">%s</td><td width="45%s">%s</td><td width="5%s">%s</td><td width="45%s">%s</td><tr>'\
                                            %('%',chr(letter),'%',str(qti_destructor.DestructorHtml.replace('&lt;','<').replace('&gt;','>')),\
                                              '%',str(num+1),'%',str(destructorTextList[num].replace('&lt;','<').replace('&gt;','>')))))
                else:
                    html_variant.append(str('<tr><td width="5%s">%s</td><td width="45%s">%s</td><td width="5%s">%s</td><td width="45%s">%s</td><tr>'\
                                            %('%',chr(letter),'%',str(qti_destructor.DestructorHtml.replace('&lt;','<').replace('&gt;','>')),\
                                              '%','','%','')))

            letter+=1
            num += 1

    else:
        html_variant.append(str('<tr><td width="5">Ответ:</td><td width="99%s"> </td><tr>'))
        correctList = destructorTextList
    html_variant.append(str('<br><br>'))
    html_answers.append(str('<tr><td width="10%s">%d</td><td width="90%s">%s</td></tr>'%('%',number,'%',','.join(answerList))))
    html_correct.append(str('<tr><td width="10%s">%d</td><td width="90%s">%s</td></tr>'%('%',number,'%',','.join(filter(lambda x:x != '',correctList)))))   
    html_variant.append(str('</table>'))
