package cn.com.qmth.stmms.biz.report.utils.module;

import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import net.sf.json.JSONObject;

import org.apache.commons.lang.StringUtils;

import cn.com.qmth.stmms.biz.exam.model.ExamQuestion;
import cn.com.qmth.stmms.biz.exam.model.ExamStudent;
import cn.com.qmth.stmms.biz.report.model.ReportSubjectClass;
import cn.com.qmth.stmms.biz.report.model.ReportSubjectClassGroup;
import cn.com.qmth.stmms.biz.report.service.ReportSubjectClassGroupService;
import cn.com.qmth.stmms.biz.report.service.ReportSubjectClassService;
import cn.com.qmth.stmms.biz.report.utils.Module;
import cn.com.qmth.stmms.biz.report.utils.QuestionCalculatorProvider;
import cn.com.qmth.stmms.biz.report.utils.ReportContext;
import cn.com.qmth.stmms.biz.report.utils.unit.BaseCalculatorUnit;
import cn.com.qmth.stmms.biz.report.utils.unit.QuestionCounter;
import cn.com.qmth.stmms.biz.utils.SpringContextHolder;

/**
 * 按科目+机组维度统计小题难度等级与区分度等级
 * 
 * @author luoshi
 *
 */
public class SubjectClassQuestionLevelModule extends SubjectQuestionLevelModule implements Module {

    protected Map<String, Set<String>> classMap;

    public SubjectClassQuestionLevelModule(ReportContext context, QuestionCalculatorProvider provider) {
        super(context, provider);
        classMap = new HashMap<String, Set<String>>();
    }

    @Override
    public void process(ExamStudent student) {
        super.process(student);

        Set<String> set = classMap.get(student.getSubjectCode());
        if (set == null) {
            set = new HashSet<>();
        }
        set.add(student.getClassName());
        classMap.put(student.getSubjectCode(), set);
    }

    @Override
    protected void beforeSave() {
        // paperType集合
        Map<String, Set<String>> paperTypes = new HashMap<String, Set<String>>();
        // 遍历客观题
        for (Entry<String, List<ExamQuestion>> entry : objectiveQuestions.entrySet()) {
            String[] keys = entry.getKey().split("\t");
            String subjectCode = keys[0];
            String paperType = keys.length > 1 ? StringUtils.trimToNull(keys[1]) : null;
            if (paperType != null) {
                Set<String> set = paperTypes.get(subjectCode);
                if (set == null) {
                    set = new HashSet<String>();
                    paperTypes.put(subjectCode, set);
                }
                set.add(paperType);
            }
            Set<String> classSet = classMap.get(subjectCode);
            if (null == classSet || classSet.isEmpty()) {
                continue;
            }
            for (String className : classSet) {
                String key = entry.getKey() + "\t" + className;
                for (ExamQuestion question : entry.getValue()) {
                    if (question.getTotalScore() == null || question.getTotalScore() == 0) {
                        continue;
                    }
                    BaseCalculatorUnit calculator = provider.getCalculator(question, className);
                    if (calculator == null) {
                        continue;
                    }
                    // 按全卷维度统计
                    findDifficulityLevelCounter(key).process(question, calculator.difficulty);
                    findDiscriminationLevelCounter(key).process(question, calculator.discrimination);
                    // 按大题维度统计
                    findDifficulityLevelCounter(getGroupKey(question, className)).process(question,
                            calculator.difficulty);
                    findDiscriminationLevelCounter(getGroupKey(question, className)).process(question,
                            calculator.discrimination);
                }
            }
        }
        // 遍历主观题
        for (Entry<String, List<ExamQuestion>> entry : subjectiveQuestions.entrySet()) {
            String subjectCode = entry.getKey();
            Set<String> classSet = classMap.get(subjectCode);
            if (null == classSet || classSet.isEmpty()) {
                continue;
            }
            for (String className : classSet) {
                for (ExamQuestion question : entry.getValue()) {
                    if (question.getTotalScore() == null || question.getTotalScore() == 0) {
                        continue;
                    }
                    BaseCalculatorUnit calculator = provider.getCalculator(question, className);
                    if (calculator == null) {
                        continue;
                    }
                    // 按全卷维度统计
                    Set<String> paperTypeSet = paperTypes.get(subjectCode);
                    if (paperTypeSet == null || paperTypeSet.isEmpty()) {
                        // 不区分paperType
                        String key = subjectCode + "\t\t" + className;
                        findDifficulityLevelCounter(key).process(question, calculator.difficulty);
                        findDiscriminationLevelCounter(key).process(question, calculator.discrimination);
                    } else {
                        // 遍历已存在的paperType
                        for (String paperType : paperTypeSet) {
                            String key = subjectCode + "\t" + paperType + "\t" + className;
                            findDifficulityLevelCounter(key).process(question, calculator.difficulty);
                            findDiscriminationLevelCounter(key).process(question, calculator.discrimination);
                        }
                    }
                    // 按大题维度统计
                    findDifficulityLevelCounter(getGroupKey(question, className)).process(question,
                            calculator.difficulty);
                    findDiscriminationLevelCounter(getGroupKey(question, className)).process(question,
                            calculator.discrimination);
                }
            }
        }
    }

    protected String getGroupKey(ExamQuestion question, String className) {
        return question.getSubjectCode() + "\t" + className + "\t" + question.isObjective() + "\t"
                + StringUtils.trimToEmpty(question.getPaperType()) + "\t" + +question.getMainNumber();
    }

    public void save() {
        beforeSave();
        ReportSubjectClassService classService = SpringContextHolder.getBean(ReportSubjectClassService.class);
        ReportSubjectClassGroupService groupService = SpringContextHolder.getBean(ReportSubjectClassGroupService.class);
        for (String key : this.difficulityLevels.keySet()) {
            String s[] = key.split("\t");
            String subjectCode = s[0];
            QuestionCounter difficulityCounter = difficulityLevels.get(key);
            QuestionCounter discriminationCounter = discriminationLevels.get(key);
            JSONObject difficulityLevel = new JSONObject();
            for (int i = 0; i < difficulityCounter.levelCount; i++) {
                JSONObject value = new JSONObject();
                value.accumulate("questionCount", difficulityCounter.totalCount[i]);
                value.accumulate("fullScore", difficulityCounter.totalScore[i]);
                String level = null;
                switch (i) {
                case 0:
                    level = "high";
                    break;
                case 1:
                    level = "middle";
                    break;
                case 2:
                    level = "low";
                    break;
                }
                if (level != null) {
                    difficulityLevel.accumulate(level, value);
                }
            }
            JSONObject discriminationLevel = new JSONObject();
            for (int i = 0; i < discriminationCounter.levelCount; i++) {
                JSONObject value = new JSONObject();
                value.accumulate("questionCount", discriminationCounter.totalCount[i]);
                value.accumulate("fullScore", discriminationCounter.totalScore[i]);
                String level = null;
                switch (i) {
                case 0:
                    level = "excellent";
                    break;
                case 1:
                    level = "good";
                    break;
                case 2:
                    level = "general";
                    break;
                case 3:
                    level = "bad";
                    break;
                }
                if (level != null) {
                    discriminationLevel.accumulate(level, value);
                }
            }
            if (s.length == 3) {
                String className = s[2];
                ReportSubjectClass r = classService.findOne(context.getExamId(), subjectCode, className);
                r.setDifficulityLevel(difficulityLevel.toString());
                r.setDiscriminationLevel(discriminationLevel.toString());
                classService.save(r);
            }
            if (s.length >= 5) {
                String className = s[1];
                Boolean objective = Boolean.parseBoolean(s[2]);
                String paperType = StringUtils.trimToNull(s[3]);
                Integer mainNumber = Integer.parseInt(s[4]);
                ReportSubjectClassGroup r = groupService.findOne(context.getExamId(), subjectCode, className,
                        objective, paperType, mainNumber);
                r.setDifficulityLevel(difficulityLevel.toString());
                r.setDiscriminationLevel(discriminationLevel.toString());
                groupService.save(r);
            }
        }
    }
}
