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

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

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.exam.service.ExamQuestionService;
import cn.com.qmth.stmms.biz.exam.service.query.ExamQuestionSearchQuery;
import cn.com.qmth.stmms.biz.report.model.ReportSubjectGroup;
import cn.com.qmth.stmms.biz.report.service.ReportSubjectGroupService;
import cn.com.qmth.stmms.biz.report.utils.Module;
import cn.com.qmth.stmms.biz.report.utils.QuestionGroup;
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.utils.ScoreItem;
import cn.com.qmth.stmms.biz.utils.SpringContextHolder;

public class SubjectGroupModule implements Module {

    protected Map<String, BaseCalculatorUnit> calculators;

    protected ReportContext context;

    public static final int UN_SELECTIVE_SCORE = -1;

    public SubjectGroupModule(ReportContext context) {
        this.calculators = new HashMap<String, BaseCalculatorUnit>();
        this.context = context;
    }

    public void process(ExamStudent student) {
        if (student.isUpload() && !student.isAbsent() && !student.isBreach() && student.getSubject() != null) {
            double totalScore = student.getTotalScore();
            // 遍历客观题
            process(student.getScoreList(true), student.getObjectiveQuestionList(), student, totalScore, true);
            // 遍历主观题
            process(student.getScoreList(false), student.getSubjectiveQuestionList(), student, totalScore, false);
        }
    }

    private void process(List<ScoreItem> scoreList, List<ExamQuestion> questionList, ExamStudent student,
            double totalScore, boolean objective) {
        if (scoreList == null || questionList == null) {
            return;
        }
        Map<String, QuestionGroup> map = new HashMap<String, QuestionGroup>();
        int scoreCount = scoreList.size();
        for (int i = 0; i < questionList.size(); i++) {
            ExamQuestion question = questionList.get(i);
            String groupKey = question.getMainNumber() + "/t" + objective;
            if (question.getTotalScore() == null || question.getTotalScore() == 0) {
                continue;
            }
            ScoreItem item = scoreCount > i ? scoreList.get(i) : null;
            QuestionGroup group = map.get(groupKey);
            if (group == null) {
                group = new QuestionGroup(objective, question.getMainNumber(), question.getPaperType());
                map.put(groupKey, group);
            }
            double score = item != null && item.getScore() != UN_SELECTIVE_SCORE ? item.getScore() : 0;
            group.incrTotalScore(score);
            group.incrFullScore(question.getTotalScore());
        }
        for (Entry<String, QuestionGroup> entry : map.entrySet()) {
            QuestionGroup group = entry.getValue();
            if (group.getFullScore() == 0) {
                continue;
            }
            findCalculator(getKey(student, group)).process(group.getTotalScore(), group.getFullScore(), totalScore);
        }
    }

    public String getKey(ExamStudent student, QuestionGroup group) {
        return student.getSubjectCode() + "\t" + group.isObjective() + "\t"
                + StringUtils.trimToEmpty(group.getPaperType()) + "\t" + group.getMainNumber();
    }

    public void save() {
        ReportSubjectGroupService service = SpringContextHolder.getBean(ReportSubjectGroupService.class);
        ExamQuestionService questionService = SpringContextHolder.getBean(ExamQuestionService.class);
        for (String key : this.calculators.keySet()) {
            String s[] = key.split("\t");
            if (s.length > 3) {
                String subjectCode = s[0];
                Boolean objective = Boolean.parseBoolean(s[1]);
                String paperType = s[2];
                Integer mainNumber = Integer.parseInt(s[3]);
                BaseCalculatorUnit unit = calculators.get(key);
                ReportSubjectGroup r = new ReportSubjectGroup();
                r.setExamId(this.context.getExamId());
                r.setSubjectCode(subjectCode);
                r.setSubjectName(context.getSubject(subjectCode).getName());
                r.setGroupName(context.getGroup(key).getMainTitle());
                r.setGroupNumber(mainNumber);
                r.setMaxScore(unit.maxScore);
                r.setMinScore(unit.minScore);
                r.setAvgScore(unit.avgScore);
                r.setTotalScore(unit.fullScore);
                r.setStdev(unit.stdev);
                r.setCoefficient(unit.coefficient);
                r.setScoreRate(unit.difficulty);
                r.setZeroCount(unit.zeroCount);
                r.setFullCount(unit.fullCount);
                r.setObjective(objective);
                r.setDifficulty(unit.difficulty);
                r.setDiscrimination(unit.discrimination);
                r.setRealityCount(unit.count);

                paperType = StringUtils.trimToNull(paperType);
                ExamQuestionSearchQuery query = new ExamQuestionSearchQuery();
                query.setExamId(context.getExamId());
                query.setSubjectCode(subjectCode);
                query.setObjective(objective);
                query.setTotalScoreGt(0d);
                query.setPaperType(paperType);
                query.setMainNumber(mainNumber);
                int questionCount = (int) questionService.countByQuery(query);
                r.setQuestionCount(questionCount);
                r.setPaperType(paperType);
                service.save(r);
            }
        }
    }

    private BaseCalculatorUnit findCalculator(String key) {
        BaseCalculatorUnit unit = calculators.get(key);
        if (unit == null) {
            unit = new BaseCalculatorUnit();
            calculators.put(key, unit);
        }
        return unit;
    }

}
