package cn.com.qmth.examcloud.core.questions.service.export;

import java.io.File;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.commons.collections.CollectionUtils;
import org.springframework.stereotype.Service;

import cn.com.qmth.examcloud.api.commons.security.bean.User;
import cn.com.qmth.examcloud.core.questions.base.CommonUtils;
import cn.com.qmth.examcloud.core.questions.base.enums.ExamFileType;
import cn.com.qmth.examcloud.core.questions.base.enums.ExportTemplateType;
import cn.com.qmth.examcloud.core.questions.base.enums.ExportType;
import cn.com.qmth.examcloud.core.questions.base.enums.PaperSeqMode;
import cn.com.qmth.examcloud.core.questions.base.question.enums.QuesStructType;
import cn.com.qmth.examcloud.core.questions.dao.entity.ExamPaper;
import cn.com.qmth.examcloud.core.questions.dao.entity.ExportStructure;
import cn.com.qmth.examcloud.core.questions.dao.entity.ExtractConfig;
import cn.com.qmth.examcloud.core.questions.dao.entity.Question;
import cn.com.qmth.examcloud.core.questions.dao.entity.QuestionTypeNum;
import cn.com.qmth.examcloud.core.questions.service.bean.dto.DownloadPaperDto;
import cn.com.qmth.examcloud.core.questions.service.bean.dto.PaperDetailExp;
import cn.com.qmth.examcloud.core.questions.service.bean.dto.PaperDetailUnitExp;
import cn.com.qmth.examcloud.core.questions.service.bean.dto.PaperExp;
import cn.com.qmth.examcloud.core.questions.service.util.ExportPaperUtil;

/**
 * @author chenken
 * @date 2017年7月31日 上午9:21:51
 * @company QMTH
 * @description 电子科技大学导出、上传文件service
 */
@Service("dzkdExportPaperService")
public class DzkdExportPaperService extends ExportPaperAbstractService {

	@Override
    public void downloadPaper(DownloadPaperDto dto) throws Exception {
        PaperExp paperExp = initPaperExp(dto);
        if (paperExp != null) {
        	// 电子科大独有
        	setSplitPaperDetailExp(paperExp, paperExp.getPaperDetails());
            String paperfileName = paperExp.getName() + "_" + paperExp.getCourseNo() + "_"
                    + ExamFileType.PAPER.getName() + DOCX_SUFFIX;
            File directory = new File(TEMP_FILE_EXP + File.separator + dto.getZipFileName());
            ExportPaperUtil.createPaperDocFile(dto.getRootOrgId(),paperExp, directory,paperfileName, ExportTemplateType.PAPER_EXPORT);
        }
    }

    @Override
    public void downloadPaperAnswer(DownloadPaperDto dto) throws Exception {
        PaperExp paperExp = initPaperExp(dto);
        if (paperExp != null) {
            // 电子科大独有
            setSplitPaperDetailExp(paperExp, paperExp.getPaperDetails());
            String answerFileName = paperExp.getName() + "_" + paperExp.getCourseNo() + "_"
                    + ExamFileType.ANSWER.getName() + DOCX_SUFFIX;
            File directory = new File(TEMP_FILE_EXP + File.separator + dto.getZipFileName());
            ExportPaperUtil.createPaperDocFile(dto.getRootOrgId(),paperExp, directory,answerFileName, ExportTemplateType.ANWSER_EXPORT);
        }
    }

    /**
     * 对相同类型的大题分组，生成不同的集合放入小题，再对小题排序
     */
    @Override
    public void sortPaperDetailUnits(List<PaperDetailExp> details) {
        int index = 0;
        Map<Long, List<PaperDetailUnitExp>> map = new HashMap<>();

        // 循环所有大题,将同类型的小题放到同一个集合下面
        for (PaperDetailExp detail : details) {
            // 单选，多选，判断放在同一集合下排序
            List<PaperDetailUnitExp> units;
            Long sortNumber = detail.getSortNumber();
            // 前四道大题为客观题区
            if (sortNumber < 5L) {
                units = map.get(sortNumber);
                if (units == null) {
                    units = new ArrayList<>();
                }
                units.addAll(detail.getPaperDetailUnits());
                map.put(sortNumber, units);
            } else {
                units = new ArrayList<>();
                units.addAll(detail.getPaperDetailUnits());
                map.put(sortNumber + index, units);
                index++;
            }
        }

        // 循环所有小题，给小题排序
        for (Long sortNumber : map.keySet()) {
            List<PaperDetailUnitExp> utils = map.get(sortNumber);
            if (CollectionUtils.isEmpty(utils)) {
                continue;
            }

            int number = 1;// 小题号
            for (int i = 0; i < utils.size(); i++) {
                PaperDetailUnitExp unit = utils.get(i);
                if (unit.getQuestionType() == QuesStructType.NESTED_ANSWER_QUESTION) {
                    List<Question> subQuestions = unit.getQuestion().getSubQuestions();
                    for (int j = 0; j < subQuestions.size(); j++) {
                        subQuestions.get(j).setNumber(number + j);
                    }
                    number += subQuestions.size();
                } else {
                    unit.setNumber(number);
                    number++;
                }
            }
        }
    }

    /**
     * 设置大题标题,并将大题分类 主观题 客观题
     */
    @Override
    public void setExportQuestionTitle(List<PaperDetailExp> details, boolean isWord) {
        if (CollectionUtils.isEmpty(details)) {
            return;
        }

        int firstBlank = 0, lastBlank = 0;
        final String style = "<em class=\"e_num\">%s</em>";

        for (PaperDetailExp detail : details) {
            String perQuesScore = checkPaperDetailUnitScore(detail);
            if (perQuesScore != null) {
                perQuesScore = CommonUtils.clearZeroPoint(perQuesScore);
                if (!isWord) {
                    perQuesScore = String.format(style, perQuesScore);
                }
                perQuesScore = String.format("每小题%s分，", perQuesScore);
            } else {
                perQuesScore = "";// 每题分数不一致则不注明
            }

            QuesStructType type = detail.getPaperDetailUnits().get(0).getQuestionType();
            String detailScore = CommonUtils.formatValue(detail.getScore());
            String unitCount = String.valueOf(detail.getUnitCount());

            if (!isWord) {
                detailScore = String.format(style, detailScore);
                unitCount = String.format(style, unitCount);
            }
            String title = String.format("（本大题共%s小题，%s共%s分）", unitCount, perQuesScore, detailScore);

            if (type == QuesStructType.SINGLE_ANSWER_QUESTION) {
                detail.setTitleDetail("在每小题列出的备选项中只有一个符合题目要求的，请将其选出并将“答题卡”的相应代码涂黑，错涂、多涂或未涂均无分");
            } else if (type == QuesStructType.MULTIPLE_ANSWER_QUESTION) {
                detail.setTitleDetail("在每小题列出的备选项中有一个或多个符合题目要求的，请将符合项选出并将“答题卡”的相应代码涂黑");
            } else if (type == QuesStructType.BOOL_ANSWER_QUESTION) {
                detail.setTitleDetail("正确的填涂A、错误填涂B。错涂、多涂或未涂均无分");
            } else if (type == QuesStructType.FILL_BLANK_QUESTION) {
                // 计算填空题空格数量
                int blanksNumbers = blanksNumbers(detail);

                // 设置填空题题干中 开始空格 和 结束空格
                lastBlank = firstBlank + blanksNumbers;

                String perFillScore = checkPaperDetailUnitblanksScore(detail);
                if (perFillScore != null) {
                    perFillScore = CommonUtils.clearZeroPoint(perFillScore);
                    if (!isWord) {
                        perFillScore = String.format(style, perFillScore);
                    }
                    perFillScore = String.format("每空%s分，", perFillScore);
                } else {
                    perFillScore = "";// 每空分数不一致则不注明
                }

                title = String.format("（本大题共%s个空格，将每空答在答题卡“%s-%s”相应的序号上，%s共%s分）", blanksNumbers, (firstBlank + 1),
                        lastBlank, perFillScore, detailScore);
                firstBlank = lastBlank;
            }

            detail.setTitle(title);
        }
    }

    /**
     * 计算每个大题所有填空题空格数量
     *
     * @param paperDetailExp
     * @return
     */
    private int blanksNumbers(PaperDetailExp paperDetailExp) {
        List<PaperDetailUnitExp> paperDetailUnitExps = paperDetailExp.getPaperDetailUnits();
        int blanksNumbers = 0;
        for (PaperDetailUnitExp paperDetailUnitExp : paperDetailUnitExps) {
            String str = paperDetailUnitExp.getQuestion().getQuesAnswer();
            if (str.indexOf("##") > -1) {
                // 将所有（ 替换为空
                String str1 = str.replaceAll("##", "");
                blanksNumbers += ((str.length() - str1.length()) / 2 + 1);
            } else {
                blanksNumbers += 1;
            }
        }
        return blanksNumbers;
    }

    /**
     * 计算每个小题所有填空题空格数量
     */
    private int blanksNumbers(PaperDetailUnitExp unitExp) {
        int blanksNumbers = 0;
        String str = unitExp.getQuestion().getQuesAnswer();
        if (str.indexOf("##") > -1) {
            // 将所有（ 替换为空
            String str1 = str.replaceAll("##", "");
            blanksNumbers += ((str.length() - str1.length()) / 2 + 1);
        } else {
            blanksNumbers += 1;
        }
        return blanksNumbers;
    }

    /**
     * 校验大题下的每个填空题空格分数是否一样
     *
     * @param paperDetailExp
     * @return 如果分数一样，返回分数 如果分数不一样，返回 null
     */
    protected String checkPaperDetailUnitblanksScore(PaperDetailExp paperDetailExp) {
        List<PaperDetailUnitExp> paperDetailUnitExps = paperDetailExp.getPaperDetailUnits();
        Set<Double> scoreSet = new HashSet<>();
        for (PaperDetailUnitExp unitExp : paperDetailUnitExps) {
            int blanksNumbers = blanksNumbers(unitExp);
            double everyBlank = unitExp.getScore() / blanksNumbers;
            scoreSet.add(everyBlank);
        }
        if (scoreSet.size() == 1) {
            return scoreSet.iterator().next() + "";
        }
        return null;
    }

    /**
     * 添加主观题与客观题
     *
     * @param paperDetailExps
     */
    public void setSplitPaperDetailExp(PaperExp PaperExp, List<PaperDetailExp> paperDetailExps) {
        // 客观题
        List<PaperDetailExp> objectiveDetails = new ArrayList<PaperDetailExp>();
        // 主观题
        List<PaperDetailExp> subjectiveDetails = new ArrayList<PaperDetailExp>();
        for (PaperDetailExp paperDetailExp : paperDetailExps) {
            Long type = paperDetailExp.getSortNumber();
            if (type < 5L) {
                objectiveDetails.add(paperDetailExp);
            } else {
                subjectiveDetails.add(paperDetailExp);
            }
        }
        PaperExp.setObjectiveDetails(objectiveDetails);
        PaperExp.setSubjectiveDetails(subjectiveDetails);
        // 主观题 客观题的标题显示
        showTitle(PaperExp);
    }

    /**
     * 主观题 客观题的标题显示
     */
    private void showTitle(PaperExp paperExp) {
        String title = "";
        List<PaperDetailExp> objectiveDetails = paperExp.getObjectiveDetails();
        List<PaperDetailExp> subjectiveDetails = paperExp.getSubjectiveDetails();
        // 设置客观题的标题
        if (objectiveDetails != null && objectiveDetails.size() > 0) {
            Double score = 0.0;
            for (PaperDetailExp objectiveDetail : objectiveDetails) {
                score += objectiveDetail.getScore();
            }
            String scores = BigDecimal.valueOf(score).stripTrailingZeros().toPlainString();
            // 判断是否有主观题
            if (subjectiveDetails == null || subjectiveDetails.size() < 1) {
                title = "客观题（总分" + scores + "分）";
                paperExp.setObjectiveTitle(title);
            } else {
                title = "第一部分" + "    " + "客观题（总分" + scores + "分）";
            }
            paperExp.setObjectiveTitle(title);
        }
        if (subjectiveDetails != null && subjectiveDetails.size() > 0) {
            Double score = 0.0;
            for (PaperDetailExp objectiveDetail : subjectiveDetails) {
                score += objectiveDetail.getScore();
            }
            String scores = BigDecimal.valueOf(score).stripTrailingZeros().toPlainString();
            // 判断是否有客观题
            if (objectiveDetails == null || objectiveDetails.size() < 1) {
                title = "主观题（总分" + scores + "分）";
                paperExp.setSubjectiveTitle(title);
            } else {
                title = "第二部分" + "    " + "主观题（总分" + scores + "分）";
            }
            paperExp.setSubjectiveTitle(title);
        }
    }

    @Override
    public void uploadFile(ExtractConfig extractConfig, String paperId, ExportStructure exportStructure,
            User accessUser, ExamPaper examPaper,PaperSeqMode seqMode){
    	DownloadPaperDto dto=new DownloadPaperDto();
    	dto.setPaperId(paperId);
    	dto.setSeqMode(seqMode);
        PaperExp paperExp = initPaperExp(dto);
        setSplitPaperDetailExp(paperExp, paperExp.getPaperDetails());
        if (paperExp != null) {
            String currNum = CommonUtils.getCurNum();
            // 没有试卷结构导出设置
            if (exportStructure == null) {
                // 上传试卷
                uploadPaperOrAnswerFile(paperExp, extractConfig, accessUser, currNum,ExportTemplateType.PAPER_EXPORT, ExamFileType.PAPER, examPaper);
                // 上传答案
                uploadPaperOrAnswerFile(paperExp, extractConfig, accessUser, currNum,ExportTemplateType.ANWSER_EXPORT, ExamFileType.ANSWER, examPaper);
            } else if (exportStructure != null && exportStructure.getExportType() == ExportType.NORMAL) {
                List<QuestionTypeNum> questionTypeNums = exportStructure.getQuestionTypeNums();
                // 检查试卷中客观题的数量是否大于试卷导出设置中的设置的数量
                checkObjectiveDetailsNum(paperExp, questionTypeNums);
                // 上传试卷
                uploadPaperOrAnswerFile(paperExp, extractConfig, accessUser, currNum,ExportTemplateType.PAPER_EXPORT, ExamFileType.PAPER, examPaper);
                // 上传答案
                uploadPaperOrAnswerFile(paperExp, extractConfig, accessUser, currNum,ExportTemplateType.ANWSER_EXPORT, ExamFileType.ANSWER, examPaper);
                // 上传试卷结构 不能在上传试卷和答案之前
                uploadPaperStructure(paperExp, extractConfig, accessUser, currNum, questionTypeNums, examPaper);
            } else if (exportStructure != null && exportStructure.getExportType() == ExportType.ONLINE) {
                // 上传机考JSON文件
                uploadComputerTestFile(extractConfig, accessUser, examPaper);
            }
        }
    }

}
