package cn.com.qmth.stmms.biz.exam.service.impl;

import java.util.*;

import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import cn.com.qmth.stmms.biz.common.BaseQueryService;
import cn.com.qmth.stmms.biz.exam.dao.SelectiveGroupDao;
import cn.com.qmth.stmms.biz.exam.model.ExamQuestion;
import cn.com.qmth.stmms.biz.exam.model.SelectiveGroup;
import cn.com.qmth.stmms.biz.exam.service.ExamQuestionService;
import cn.com.qmth.stmms.biz.exam.service.ExamSubjectService;
import cn.com.qmth.stmms.biz.exam.service.SelectiveGroupService;
import cn.com.qmth.stmms.common.enums.ScorePolicy;
import cn.com.qmth.stmms.common.utils.BigDecimalUtils;

@Service("selectiveGroupService")
public class SelectiveGroupServiceImpl extends BaseQueryService<SelectiveGroup> implements SelectiveGroupService {

    @Autowired
    private SelectiveGroupDao selectiveGroupDao;

    @Autowired
    private ExamQuestionService questionService;

    @Autowired
    private ExamSubjectService subjectService;

    @Transactional
    @Override
    public SelectiveGroup save(SelectiveGroup group) {
        return selectiveGroupDao.save(group);
    }

    @Transactional
    @Override
    public void save(List<SelectiveGroup> list) {
        if (!list.isEmpty()) {
            selectiveGroupDao.save(list);
        }
    }

    @Override
    public SelectiveGroup findOne(int examId, String subjectCode, int mainNumber) {
        return selectiveGroupDao.findOne(examId, subjectCode, mainNumber);
    }

    @Override
    public List<SelectiveGroup> findByExamIdAndSubjectCode(int examId, String code) {
        return selectiveGroupDao.findByExamIdAndSubjectCode(examId, code);
    }

    @Transactional
    @Override
    public void deleteByExamIdAndSubjectCodeAndSelectiveIndex(int examId, String subjectCode, int selectiveIndex) {
        selectiveGroupDao.deleteByExamIdAndSubjectCodeAndSelectiveIndex(examId, subjectCode, selectiveIndex);
        if (countByExamIdAndSubjectCode(examId, subjectCode) <= 0) {
            subjectService.updateSelective(examId, subjectCode, false);
        }
        subjectService.updateScore(examId, subjectCode, false,
                questionService.sumTotalScore(examId, subjectCode, false));
    }

    @Override
    public List<SelectiveGroup> findIndexByExamIdAndSubjectCode(int examId, String subjectCode) {
        Map<Integer, List<SelectiveGroup>> map = this.findGroupByExamIdAndSubjectCode(examId, subjectCode);
        List<ExamQuestion> questionList = questionService.findMainByExamAndSubjectAndObjective(examId, subjectCode,
                false);
        Map<Integer, String> mainTileMap = new HashMap<Integer, String>();
        Map<Integer, Double> mainScoreMap = new HashMap<Integer, Double>();
        for (ExamQuestion question : questionList) {
            mainTileMap.put(question.getMainNumber(), question.getMainTitle());
            mainScoreMap.put(question.getMainNumber(), question.getTotalScore());
        }
        List<SelectiveGroup> result = new ArrayList<SelectiveGroup>();
        for (Integer key : map.keySet()) {
            List<SelectiveGroup> indexGroup = map.get(key);
            Set<String> mainTitles = new LinkedHashSet<>();
            double partScore = 0;
            int selectivePart = 0;
            for (SelectiveGroup selectiveGroup : indexGroup) {
                // 显示分组下所有题目名称
                mainTitles.add(mainTileMap.get(selectiveGroup.getMainNumber()));
                // 显示最大的part
                if (selectivePart < selectiveGroup.getSelectivePart()) {
                    selectivePart = selectiveGroup.getSelectivePart();
                }
                // 计算分组一个part的分数
                if (selectiveGroup.getSelectivePart() == 1) {
                    partScore = partScore + mainScoreMap.get(selectiveGroup.getMainNumber());
                }
            }
            SelectiveGroup group = indexGroup.get(0);
            group.setSelectivePart(selectivePart);
            group.setTitle(StringUtils.join(mainTitles, ","));
            group.setPartScore(partScore);
            result.add(group);
        }
        return result;
    }

    @Override
    public long countByExamIdAndSubjectCode(int examId, String subjectCode) {
        return selectiveGroupDao.countByPkExamIdAndPkSubjectCode(examId, subjectCode);
    }

    @Override
    public Map<Integer, List<SelectiveGroup>> findGroupByExamIdAndSubjectCode(int examId, String subjectCode) {
        List<SelectiveGroup> list = selectiveGroupDao.findByExamIdAndSubjectCode(examId, subjectCode);
        Map<Integer, List<SelectiveGroup>> map = new HashMap<Integer, List<SelectiveGroup>>();
        for (SelectiveGroup selectiveGroup : list) {
            List<SelectiveGroup> indexGroup = map.get(selectiveGroup.getSelectiveIndex());
            if (indexGroup == null) {
                indexGroup = new ArrayList<SelectiveGroup>();
            }
            indexGroup.add(selectiveGroup);
            map.put(selectiveGroup.getSelectiveIndex(), indexGroup);
        }
        return map;
    }

    @Override
    public int findMaxIndexByExamIdAndSubjectCode(int examId, String subjectCode) {
        List<SelectiveGroup> groups = selectiveGroupDao.findByExamIdAndSubjectCode(examId, subjectCode);
        int number = 0;
        for (SelectiveGroup group : groups) {
            if (number < group.getSelectiveIndex()) {
                number = group.getSelectiveIndex();
            }
        }
        return number;
    }

    @Transactional
    @Override
    public void updateScorePolicy(int examId, String subjectCode, Integer selectiveIndex, ScorePolicy scorePolicy) {
        selectiveGroupDao.updateScorePolicy(examId, subjectCode, selectiveIndex, scorePolicy);
    }

    @Override
    public double sumScoreByExamIdAndSubjectCode(int examId, String subjectCode) {
        List<ExamQuestion> questionList = questionService.findByExamAndSubjectAndObjective(examId, subjectCode, false);
        if (questionList.isEmpty()) {
            return 0d;
        }
        Map<Integer, Double> mainScoreMap = new HashMap<Integer, Double>();
        for (ExamQuestion question : questionList) {
            Double mainScore = mainScoreMap.get(question.getMainNumber());
            if (mainScore == null) {
                mainScoreMap.put(question.getMainNumber(), question.getTotalScore());
            } else {
                mainScoreMap.put(question.getMainNumber(), BigDecimalUtils.add(mainScore, question.getTotalScore()));
            }
        }

        Map<Integer, List<SelectiveGroup>> indexMap = this.findGroupByExamIdAndSubjectCode(examId, subjectCode);
        double totalScore = 0d;
        for (Integer index : indexMap.keySet()) {
            // 循环选做题组
            List<SelectiveGroup> indexGroup = indexMap.get(index);
            Integer selectiveCount = 0;
            double partScore = 0d;
            for (SelectiveGroup selectiveGroup : indexGroup) {
                if (selectiveCount == 0) {
                    selectiveCount = selectiveGroup.getSelectiveCount();
                }
                if (selectiveGroup.getSelectivePart().intValue() == 1) {
                    partScore = BigDecimalUtils.add(partScore, mainScoreMap.get(selectiveGroup.getMainNumber()));
                }
            }
            totalScore = BigDecimalUtils.add(totalScore, BigDecimalUtils.mul(partScore, selectiveCount));
        }
        return totalScore;
    }
}
