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

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

import cn.com.qmth.stmms.biz.exam.dao.ExamStudentDao;
import cn.com.qmth.stmms.biz.exam.model.ExamStudent;
import cn.com.qmth.stmms.biz.report.model.ReportSubject;
import cn.com.qmth.stmms.biz.report.model.ReportSubjectRange;
import cn.com.qmth.stmms.biz.report.service.ReportSubjectRangeService;
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.RangeCounter;
import cn.com.qmth.stmms.biz.utils.SpringContextHolder;
import cn.com.qmth.stmms.common.utils.BigDecimalUtils;
import net.sf.json.JSONObject;

public class SubjectRangeModule implements Module {

    private Map<String, RangeCounter> counters;

    private ReportContext context;

    public SubjectRangeModule(ReportContext context) {
        this.counters = new HashMap<String, RangeCounter>();
        this.context = context;
    }

    @Override
    public void process(ExamStudent student) {
        if (student.isUpload() && !student.isAbsent() && !student.isBreach() && student.getSubject() != null) {
            findCounter(getKey(student)).process(student.getTotalScore());
        }
    }

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

    @Override
    public void save() {
        ReportSubjectRangeService service = SpringContextHolder.getBean(ReportSubjectRangeService.class);
        for (String subjectCode : this.counters.keySet()) {
            RangeCounter counter = counters.get(subjectCode);
            ReportSubjectRange subjectRange = new ReportSubjectRange();
            subjectRange.setExamId(this.context.getExamId());
            subjectRange.setSubjectCode(subjectCode);
            subjectRange.setSubjectName(context.getSubject(subjectCode).getName());
            subjectRange.setLevel(context.getSubject(subjectCode).getLevel());
            subjectRange.setCount0_49(counter.countGeAndLt(0d, 50d));
            subjectRange.setCount50_59(counter.countGeAndLt(50d, 60d));
            subjectRange.setCount60_69(counter.countGeAndLt(60d, 70d));
            subjectRange.setCount70_79(counter.countGeAndLt(70d, 80d));
            subjectRange.setCount80_89(counter.countGeAndLt(80d, 90d));
            subjectRange.setCount90_100(counter.countGeAndLt(90d, null));
            subjectRange.setLt60(counter.countGeAndLt(0d, 60d));
            subjectRange.setMte60(counter.countGeAndLt(60d, null));
            subjectRange.setTotalCount(counter.totalCount);
            subjectRange.setPercent0_49(counter.countGeAndLt(0d, 50d) * 1.0 / counter.totalCount);
            subjectRange.setPercent50_59(counter.countGeAndLt(50d, 60d) * 1.0 / counter.totalCount);
            subjectRange.setPercent60_69(counter.countGeAndLt(60d, 70d) * 1.0 / counter.totalCount);
            subjectRange.setPercent70_79(counter.countGeAndLt(70d, 80d) * 1.0 / counter.totalCount);
            subjectRange.setPercent80_89(counter.countGeAndLt(80d, 90d) * 1.0 / counter.totalCount);
            subjectRange.setPercent90_100(counter.countGeAndLt(90d, null) * 1.0 / counter.totalCount);
            subjectRange.setPercent_lt60(counter.countGeAndLt(0d, 60d) * 1.0 / counter.totalCount);
            subjectRange.setPercent_mte60(counter.countGeAndLt(60d, null) * 1.0 / counter.totalCount);
            service.save(subjectRange);

            ReportSubjectService subjectService = SpringContextHolder.getBean(ReportSubjectService.class);
            ExamStudentDao studentDao = SpringContextHolder.getBean(ExamStudentDao.class);
            ReportSubject subject = subjectService.findOne(this.context.getExamId(), subjectCode);
            JSONObject rangeLevel = new JSONObject();
            double highCount = Math.ceil(context.getHighValueConfig() * subject.getRealityCount() * 0.01);
            double lowCount = Math.ceil(context.getLowValueConfig() * subject.getRealityCount() * 0.01);
            List<BigDecimal> highScore = studentDao.findHighCountTotalSocreByExamIdAndSubjectCode(context.getExamId(),
                    subjectCode, (int) highCount);
            List<BigDecimal> lowScore = studentDao.findLowCountTotalSocreByExamIdAndSubjectCode(context.getExamId(),
                    subjectCode, (int) lowCount);
            rangeLevel.accumulate("highScore",
                    highScore.isEmpty() ? 0 : highScore.get(highScore.size() - 1).doubleValue());
            rangeLevel.accumulate("lowScore", lowScore.isEmpty() ? 0 : lowScore.get(lowScore.size() - 1).doubleValue());
            subject.setRangeLevel(rangeLevel.toString());

            JSONObject scoreRange = new JSONObject();
            double rate = 0.25;
            double length = BigDecimalUtils.div(subject.getTotalScore(), rate);
            for (int i = 0; i < length + 1; i++) {
                scoreRange.accumulate(String.valueOf(i * rate), counter.countGeAndLt(i * rate, (i + 1) * rate));
            }
            subject.setScoreRange(scoreRange.toString());
            subjectService.save(subject);
        }

    }

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

}
