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

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

import cn.com.qmth.stmms.biz.exam.model.ExamStudent;
import cn.com.qmth.stmms.biz.exam.model.ExamSubject;
import cn.com.qmth.stmms.biz.exam.service.ExamQuestionService;
import cn.com.qmth.stmms.biz.exam.service.ExamStudentService;
import cn.com.qmth.stmms.biz.exam.service.query.ExamQuestionSearchQuery;
import cn.com.qmth.stmms.biz.report.model.ReportSubject;
import cn.com.qmth.stmms.biz.report.service.ReportSubjectService;
import cn.com.qmth.stmms.biz.report.utils.Module;
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.BaseCounter;
import cn.com.qmth.stmms.biz.utils.SpringContextHolder;

public class SubjectModule implements Module {

    protected Map<String, BaseCalculatorUnit> units;

    protected Map<String, BaseCounter> counters;

    protected ReportContext context;

    public SubjectModule(ReportContext context) {
        this.units = new HashMap<String, BaseCalculatorUnit>();
        this.counters = new HashMap<String, BaseCounter>();
        this.context = context;
    }

    public void process(ExamStudent student) {
        ExamSubject subject = student.getSubject();
        if (subject != null) {
            String key = getKey(student);
            if (student.isUpload() && !student.isAbsent() && !student.isBreach()) {
                findCalculator(key).process(student.getTotalScore(), subject.getTotalScore(), student.getTotalScore());
            }
            findCounter(key).process(student);
        }
    }

    public String getKey(ExamStudent student) {
        return student.getSubjectCode();
    }

    public void save() {
        ReportSubjectService service = SpringContextHolder.getBean(ReportSubjectService.class);
        ExamQuestionService questionService = SpringContextHolder.getBean(ExamQuestionService.class);
        ExamStudentService studentService = SpringContextHolder.getBean(ExamStudentService.class);
        for (String subjectCode : this.counters.keySet()) {
            BaseCounter counter = counters.get(subjectCode);
            BaseCalculatorUnit unit = units.get(subjectCode);
            ReportSubject subject = new ReportSubject();
            subject.setExamId(this.context.getExamId());
            subject.setSubjectCode(subjectCode);
            subject.setSubjectName(context.getSubject(subjectCode).getName());
            subject.setTotalCount((int) studentService.countByExamIdAndSubjectCode(this.context.getExamId(),
                    subjectCode));
            subject.setAbsentCount((int) studentService.countByAbsentAndBreach(this.context.getExamId(), subjectCode,
                    true, null));
            subject.setBreachCount((int) studentService.countByAbsentAndBreach(this.context.getExamId(), subjectCode,
                    null, true));
            subject.setRealityCount(counter.realityCount);
            if (unit != null) {
                subject.setMaxScore(unit.maxScore);
                subject.setMinScore(unit.minScore);
                subject.setAvgScore(unit.avgScore);
                subject.setPassCount(unit.passCount);
                subject.setPassRate(unit.passRate);
                subject.setExcellentCount(unit.excellentCount);
                subject.setExcellentRate(unit.excellentRate);
                subject.setDifficulty(unit.difficulty);
                subject.setDiscrimination(unit.discrimination);
                subject.setCoefficient(unit.coefficient);
                subject.setStdev(unit.stdev);
                subject.setZeroCount(unit.zeroCount);
                subject.setFullCount(unit.fullCount);
                subject.setTotalScore(unit.fullScore);
            } else {
                subject.setMaxScore(0d);
                subject.setMinScore(0d);
                subject.setAvgScore(0d);
                subject.setPassCount(0);
                subject.setPassRate(0d);
            }
            List<String> paperTypes = questionService.getPaperType(context.getExamId(), subjectCode);
            String paperType = null;
            if (paperTypes.size() > 0) {
                paperType = paperTypes.get(0);
            }
            ExamQuestionSearchQuery query = new ExamQuestionSearchQuery();
            query.setExamId(context.getExamId());
            query.setSubjectCode(subjectCode);
            query.setObjective(false);
            query.setTotalScoreGt(0d);
            long subjectiveCcount = questionService.countByQuery(query);
            query.setObjective(true);
            query.setPaperType(paperType);
            long ObjectiveCcount = questionService.countByQuery(query);
            subject.setQuestionCount((int) (subjectiveCcount + ObjectiveCcount));
            service.save(subject);
        }
    }

    protected BaseCalculatorUnit findCalculator(String key) {
        BaseCalculatorUnit unit = units.get(key);
        if (unit == null) {
            unit = new BaseCalculatorUnit();
            String keys[] = key.split("\t");
            ExamSubject subject = context.getSubject(keys[0]);

            unit.passScore = subject.getTotalScore() * context.getPassScore() * 0.01;
            unit.excellentScore = subject.getTotalScore() * context.getExcellentScore() * 0.01;

            if (subject != null && subject.getPassScore() != null) {
                unit.passScore = subject.getTotalScore() * subject.getPassScore() * 0.01;
            }
            if (subject != null && subject.getExcellentScore() != null) {
                unit.excellentScore = subject.getTotalScore() * subject.getExcellentScore() * 0.01;
            }
            units.put(key, unit);
        }
        return unit;
    }

    private BaseCounter findCounter(String key) {
        BaseCounter counter = counters.get(key);
        if (counter == null) {
            counter = new BaseCounter();
            counters.put(key, counter);
        }
        return counter;
    }

}
