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

import java.io.File;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.commons.lang3.StringUtils;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.bson.types.ObjectId;
import org.docx4j.openpackaging.packages.WordprocessingMLPackage;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import cn.com.qmth.examcloud.api.commons.security.bean.User;
import cn.com.qmth.examcloud.commons.exception.StatusException;
import cn.com.qmth.examcloud.commons.util.Calculator;
import cn.com.qmth.examcloud.commons.util.JsonUtil;
import cn.com.qmth.examcloud.core.questions.base.CommonUtils;
import cn.com.qmth.examcloud.core.questions.base.converter.utils.FileUtil;
import cn.com.qmth.examcloud.core.questions.base.enums.PaperStatus;
import cn.com.qmth.examcloud.core.questions.base.enums.PaperType;
import cn.com.qmth.examcloud.core.questions.base.question.enums.QuesStructType;
import cn.com.qmth.examcloud.core.questions.base.word.DocxProcessUtil;
import cn.com.qmth.examcloud.core.questions.dao.PaperDetailRepo;
import cn.com.qmth.examcloud.core.questions.dao.PaperDetailUnitRepo;
import cn.com.qmth.examcloud.core.questions.dao.PaperRepo;
import cn.com.qmth.examcloud.core.questions.dao.QuesRepo;
import cn.com.qmth.examcloud.core.questions.dao.entity.Course;
import cn.com.qmth.examcloud.core.questions.dao.entity.Paper;
import cn.com.qmth.examcloud.core.questions.dao.entity.PaperDetail;
import cn.com.qmth.examcloud.core.questions.dao.entity.PaperDetailUnit;
import cn.com.qmth.examcloud.core.questions.dao.entity.QuesOption;
import cn.com.qmth.examcloud.core.questions.dao.entity.Question;
import cn.com.qmth.examcloud.core.questions.service.impl.CourseService;
import cn.com.qmth.examcloud.core.questions.service.temp.ImgDataUtils;
import cn.com.qmth.examcloud.core.questions.service.temp.vo.TestFillAnswer;
import cn.com.qmth.examcloud.core.questions.service.temp.vo.TestFillContent;
import cn.com.qmth.examcloud.core.questions.service.temp.vo.TestOption;
import cn.com.qmth.examcloud.core.questions.service.temp.vo.TestOptionGroup;
import cn.com.qmth.examcloud.core.questions.service.temp.vo.TestPaper;
import cn.com.qmth.examcloud.core.questions.service.temp.vo.TestQuestion;
import cn.com.qmth.examcloud.core.questions.service.temp.vo.TestQuestionInfo;
import cn.com.qmth.examcloud.web.config.SystemProperties;

@Service
public class ImportDdCollegePaperService {


    @Autowired
    private PaperRepo paperRepo;

    @Autowired
    private PaperDetailRepo paperDetailRepo;

    @Autowired
    private PaperDetailUnitRepo paperDetailUnitRepo;

    @Autowired
    private QuesRepo quesRepo;

    @Autowired
    private CourseService courseService;

    @Autowired
    private QuesTypeNameService quesTypeNameService;

//    @Autowired
//    private QuesPkgPathRepo quesPkgPathRepo;
    
    @Autowired
    private SystemProperties systemProperties;

    public void importDdCollegePaper(MultipartFile dataFile, User user, Long rootOrgId,String courseCode,String suff) {
        String tempDir = systemProperties.getTempDataDir();
        String dir = tempDir + File.separator + UUID.randomUUID() + File.separator;
        try {
            File dfile = new File(dir);
            dfile.mkdirs();
            File zfile = new File(dir + dataFile.getOriginalFilename());
            zfile.createNewFile();
            dataFile.transferTo(zfile);
            FileUtil.unZip(dfile, zfile);
            String excelFileName=dataFile.getOriginalFilename().substring(0, dataFile.getOriginalFilename().lastIndexOf("."))+".xlsx";
            resolvingImportFile(dir, excelFileName, user, rootOrgId,courseCode,suff);
        } catch (StatusException e) {
            throw e;
        } catch (Exception e) {
            throw new StatusException("100001", "导入试卷失败:" + e.getMessage(), e);
        } finally {
            FileUtil.deleteFolder(dir);
        }
    }

    private void resolvingImportFile(String dir,String excelFileName, User user, Long rootOrgId,String courseCode,String suff) throws IOException {
        XSSFWorkbook wb = null;
        try {
            wb = new XSSFWorkbook(dir + excelFileName);
            XSSFSheet sheet0 = wb.getSheetAt(0);
            Course course = courseService.getCourse(rootOrgId, courseCode);
            if (course == null) {
                throw new StatusException("200002", "课程信息不存在");
            }
            List<TestPaper> papers = new ArrayList<>();
            for (int i = 1; i <= sheet0.getLastRowNum(); i++) {
                XSSFRow row = sheet0.getRow(i);
                TestPaper tp = new TestPaper();
                tp.setId(row.getCell(0).getStringCellValue());
                tp.setName(row.getCell(1).getStringCellValue()+(suff==null?"":suff));
                tp.setTestPaperContentId(row.getCell(2).getStringCellValue());
                tp.setScore(getDoubleByString(row.getCell(3).getStringCellValue()));
                papers.add(tp);
            }
            if (papers == null || papers.size() == 0) {
                throw new StatusException("200001", "试卷信息为空");
            }
            int quesSheetIndex = 1;
            for (TestPaper testPaper : papers) {
                // 查询试题详情
                XSSFSheet quesheet = wb.getSheetAt(quesSheetIndex);
                List<TestQuestion> questions = queryTestPaper(dir, quesheet);
                quesSheetIndex++;
                // 构建大题和小题对应关系
                Map<Integer, List<TestQuestion>> map = sortPaperDetail(questions);
                // 初始化试卷
                Paper paper = initPaper(testPaper, rootOrgId + "", course, map, user);
                // 定义大题集合
                List<PaperDetail> paperDetails = new ArrayList<>();
                // 定义小题集合
                List<PaperDetailUnit> paperDetailUnits = new ArrayList<>();
                // 试题---资源 对应关系
                Set<Question> set = new LinkedHashSet<Question>();
                // 定义试卷难度
                double difficulty = 0;
                int error = 1;
                for (Integer key : map.keySet()) {
                    List<TestQuestion> dQuestions = map.get(key);
                    // 初始化大题对象
                    PaperDetail paperDetail = initPaperDetail(dQuestions, paper, user);
                    if (dQuestions != null && dQuestions.size() > 0) {
                        for (TestQuestion testQuestion : dQuestions) {
                            TestQuestionInfo testQuestionInfo = JsonUtil.fromJson(testQuestion.getJson(),
                                    TestQuestionInfo.class);
                            // 初始化试题对象
                            Question question = null;
                            try {
                                question = initQuestion(testQuestionInfo, testQuestion, course, set, difficulty, dir,
                                        quesheet);
                            } catch (Exception e) {
                                throw new StatusException("600001",
                                        "初始化试题失败 courseCode:" + courseCode + " 试卷内容ID:"
                                                + testPaper.getTestPaperContentId() + " 错误题号：" + error + " 试题ID："
                                                + testQuestion.getId() + " " + e.getMessage());
                            }
                            // 初始化小题对象
                            PaperDetailUnit paperDetailUnit = initPaperDetailUnit(paper, paperDetail, question,
                                    testQuestion, user);
                            paperDetailUnits.add(paperDetailUnit);
                            error++;
                        }
                    }
                    paperDetails.add(paperDetail);
                }
                // 保存试题资源
//                quesPkgPathRepo.saveAll(map2.values());
//                for (Map.Entry<Question, QuestionPkgPath> entry : map2.entrySet()) {
//                    entry.getKey().setQuesPkgPathId(entry.getValue().getId());
//                }
                // 计算试卷难度
                paper.setDifficultyDegree(0.5);
                // 重新计算试题序号
                Map<PaperDetail, List<PaperDetailUnit>> map3 = new LinkedHashMap<>();
                List<PaperDetailUnit> newList = null;
                for (PaperDetail paperDetail : paperDetails) {
                    for (PaperDetailUnit paperDetailUnit : paperDetailUnits) {
                        if (paperDetail.getName().equals(paperDetailUnit.getPaperDetail().getName())) {
                            if (map3.get(paperDetail) == null) {
                                newList = new ArrayList<>();
                                newList.add(paperDetailUnit);
                            } else {
                                newList = map3.get(paperDetail);
                                newList.add(paperDetailUnit);
                            }
                            map3.put(paperDetail, newList);
                        }
                    }
                }
                int number = 1;
                for (Map.Entry<PaperDetail, List<PaperDetailUnit>> entry : map3.entrySet()) {
                    for (PaperDetailUnit paperDetailUnit : entry.getValue()) {
                        paperDetailUnit.setNumber(number);
                        number++;
                    }
                }
                quesRepo.saveAll(set);
                paperRepo.save(paper);
                paperDetailRepo.saveAll(paperDetails);
                paperDetailUnitRepo.saveAll(paperDetailUnits);
                if (paperDetailUnits.size() > 0) {
                    quesTypeNameService.saveQuesTypeName(paperDetailUnits);
                }
            }

        } finally {
            if (wb != null) {
                wb.close();
            }
        }
    }

    private List<TestQuestion> queryTestPaper(String dir, XSSFSheet sheet) {
        List<TestQuestion> questions = new ArrayList<TestQuestion>();
        for (int i = 1; i <= sheet.getLastRowNum(); i++) {
            XSSFRow row = sheet.getRow(i);
            String pid = row.getCell(5).getStringCellValue();
            if ("00000000000000000000000000000000".equals(pid)) {
                TestQuestion tq = new TestQuestion();
                tq.setId(row.getCell(0).getStringCellValue());
                tq.setdNumber(getIntByString(row.getCell(1).getStringCellValue()));
                tq.setdName(row.getCell(2).getStringCellValue());
                tq.setNumber(getIntByString(row.getCell(3).getStringCellValue()));
                tq.setScore(getDoubleByString(row.getCell(4).getStringCellValue()));
                tq.setParentId(row.getCell(5).getStringCellValue());
                tq.setType(getIntByString(row.getCell(6).getStringCellValue()));
                File quesJson = new File(dir + tq.getId() + ".txt");
                if (!quesJson.exists()) {
                    throw new StatusException("300002", "试题信息文件不存在");
                }
                tq.setJson(FileUtil.readFileContent(quesJson));
                questions.add(tq);
            }
        }

        if (questions.size() == 0) {
            throw new StatusException("300001", "试题信息为空");
        }
        return questions;
    }

    private Integer getIntByString(String v) {
        if (StringUtils.isEmpty(v)) {
            return null;
        }
        return Integer.valueOf(v);
    }

    private Double getDoubleByString(String v) {
        if (StringUtils.isEmpty(v)) {
            return null;
        }
        return Double.valueOf(v);
    }

    // 将大题和小题分类
    private Map<Integer, List<TestQuestion>> sortPaperDetail(List<TestQuestion> questions) {
        Map<Integer, List<TestQuestion>> map = new LinkedHashMap<>();
        List<TestQuestion> sortQuestions = null;
        for (TestQuestion testQuestion : questions) {
            if (map.get(testQuestion.getdNumber()) == null) {
                sortQuestions = new ArrayList<TestQuestion>();
                sortQuestions.add(testQuestion);
            } else {
                sortQuestions = map.get(testQuestion.getdNumber());
                sortQuestions.add(testQuestion);
            }
            map.put(testQuestion.getdNumber(), sortQuestions);
        }
        return map;
    }

    // 初始化试卷对象
    private Paper initPaper(TestPaper testPaper, String orgId, Course course, Map<Integer, List<TestQuestion>> map,
            User user) {
        int unitCount = 0;
        Set<Integer> paperDetails = map.keySet();
        for (Map.Entry<Integer, List<TestQuestion>> entry : map.entrySet()) {
            unitCount = unitCount + entry.getValue().size();
        }
        Paper paper = new Paper();
        paper.setName(testPaper.getName());
        paper.setTitle(testPaper.getName());
        paper.setPaperType(PaperType.IMPORT);
        paper.setPaperStatus(PaperStatus.DRAFT);
        paper.setOrgId(orgId);
        paper.setCreator(user.getDisplayName());
        paper.setTotalScore(testPaper.getScore());
        paper.setCourse(course);
        paper.setCourseName(course.getName());
        paper.setCourseNo(course.getCode());
        paper.setCreateTime(CommonUtils.getCurDateTime());
        paper.setPaperDetailCount(paperDetails.size());
        paper.setUnitCount(unitCount);
        return paper;
    }

    // 初始化大题对象
    private PaperDetail initPaperDetail(List<TestQuestion> dQuestions, Paper paper, User user) {
        // 定义大题分数
        double dTotal = 0;
        PaperDetail paperDetail = new PaperDetail();
        if (dQuestions != null && dQuestions.size() > 0) {
            for (TestQuestion question : dQuestions) {
                dTotal = dTotal + question.getScore();
            }
            paperDetail.setPaper(paper);
            paperDetail.setNumber(dQuestions.get(0).getdNumber());
            paperDetail.setName(dQuestions.get(0).getdName());
            paperDetail.setScore(dTotal);
            paperDetail.setUnitCount(dQuestions.size());
            paperDetail.setCreator(user.getDisplayName());
            paperDetail.setCreateTime(CommonUtils.getCurDateTime());
        }
        return paperDetail;
    }

    // 初始化试题对象
    private Question initQuestion(TestQuestionInfo testQuestionInfo, TestQuestion testQuestion, Course course,
    		Set<Question> set, double difficulty, String dir, XSSFSheet sheet) throws Exception {
        Question question = new Question();
        question.setCreateTime(CommonUtils.getCurDateTime());
        question.setScore(testQuestion.getScore());
        question.setCourse(course);
        question.setOrgId(course.getOrgId());
        question.setHasAudio(false);
        question.setDifficulty("中");
        question.setDifficultyDegree(0.5);
        question.setPublicity(true);
        // 按试题分类初始化题干，答案，选项
        initQuestionInfo(question, testQuestionInfo, set, testQuestion, dir, sheet);
        difficulty = question.getScore() * 0.5 + difficulty;
        return question;
    }

    // 初始化题干，答案，选项,资源
    private void initQuestionInfo(Question question, TestQuestionInfo testQuestionInfo,
    		Set<Question> set, TestQuestion testQuestion, String dir, XSSFSheet sheet)
            throws Exception {
        WordprocessingMLPackage wordMLPackage = WordprocessingMLPackage.createPackage();
        // 选词填空
        if (testQuestionInfo.getQuestionType() == 14) {
            String quesBody = testQuestionInfo.getQuestionHTML();
            // 去掉<span>标签中的lang
            quesBody = replaceLang(quesBody);
            // 获取img标签
            LinkedHashMap<String, String> bodyImgList = imgList(quesBody);
            if (bodyImgList != null && bodyImgList.size() > 0) {
                int number = 1;
                for (Map.Entry<String, String> entry : bodyImgList.entrySet()) {
                    if (StringUtils.isBlank(entry.getValue())) {
                        quesBody = quesBody.replace(entry.getKey(), "##" + number + "##");
                        number++;
                    } else {
                        quesBody = quesBody.replace(entry.getKey(), entry.getValue());
                    }
                }
            }
            question.setQuesBody("<p>" + quesBody + "</p>");
            question.setQuesBodyWord(
                    DocxProcessUtil.html2Docx(wordMLPackage, CommonUtils.formatHtml(question.getQuesBody())));
            question.setQuestionType(QuesStructType.NESTED_ANSWER_QUESTION);
            List<Question> subQuestions = initSubQuestionsByOther(testQuestionInfo, wordMLPackage);
            question.setSubQuestions(subQuestions);
        }
        // 阅读理解题
        if (testQuestionInfo.getQuestionType() == 42) {
            String quesBody = testQuestionInfo.getQuestionHTML();
            // 去掉<span>标签中的lang
            quesBody = replaceLang(quesBody);
            // 获取img标签
            LinkedHashMap<String, String> bodyImgList = imgList(quesBody);
            // 替换、补全Img标签
            quesBody = replaceImg(bodyImgList, quesBody);
            question.setQuesBody("<p>" + quesBody + "</p>");
            question.setQuesBodyWord(
                    DocxProcessUtil.html2Docx(wordMLPackage, CommonUtils.formatHtml(question.getQuesBody())));
            question.setQuestionType(QuesStructType.NESTED_ANSWER_QUESTION);
            List<Question> subQues = new ArrayList<Question>();
            // 查询所有子题
            List<TestQuestion> subQuestions = querySubQuestions(testQuestion.getId(), dir, sheet);
            if (subQuestions != null && subQuestions.size() > 0) {
                for (TestQuestion testQuestion2 : subQuestions) {
                    TestQuestionInfo testQuestionInfo2 = JsonUtil.fromJson(testQuestion2.getJson(),
                            TestQuestionInfo.class);
                    Question subQuestion = new Question();
                    subQuestion.setId(new ObjectId().toString());
                    subQuestion.setDifficulty("中");
                    subQuestion.setDifficultyDegree(0.5);
                    subQuestion.setPublicity(true);
                    subQuestion.setScore(testQuestion2.getScore());
                    // 按试题分类初始化题干，答案，选项
                    initQuestionInfo(subQuestion, testQuestionInfo2, set, testQuestion2, dir, sheet);
                    subQues.add(subQuestion);
                }
                question.setSubQuestions(subQues);
            }
        }
        // 完形填空题
        if (testQuestionInfo.getQuestionType() == 15) {
            String quesBody = testQuestionInfo.getQuestionHTML();
            // 去掉<span>标签中的lang
            quesBody = replaceLang(quesBody);
            // 获取img标签
            LinkedHashMap<String, String> bodyImgList = imgList(quesBody);
            if (bodyImgList != null && bodyImgList.size() > 0) {
                int number = 1;
                for (Map.Entry<String, String> entry : bodyImgList.entrySet()) {
                    if (StringUtils.isBlank(entry.getValue())) {
                        quesBody = quesBody.replace(entry.getKey(), "##" + number + "##");
                        number++;
                    } else {
                        quesBody = quesBody.replace(entry.getKey(), entry.getValue());
                    }
                }
            }
            question.setQuesBody("<p>" + quesBody + "</p>");
            question.setQuesBodyWord(
                    DocxProcessUtil.html2Docx(wordMLPackage, CommonUtils.formatHtml(question.getQuesBody())));
            question.setQuestionType(QuesStructType.NESTED_ANSWER_QUESTION);
            // 获取所有选项
            List<TestFillAnswer> blanks = testQuestionInfo.getBlanks();
            List<Question> subQuestions = initSubQuestions(blanks, wordMLPackage);
            if (blanks != null && blanks.size() > 0 && testQuestion.getScore() != null) {
                double subScore = Calculator.divide(testQuestion.getScore(), blanks.size(), 1);
                for (Question q : subQuestions) {
                    q.setScore(subScore);
                }
            }
            question.setSubQuestions(subQuestions);
        }
        // 问答题 、 名词解释
        if (testQuestionInfo.getQuestionType() == 60 || testQuestionInfo.getQuestionType() == 69 ||testQuestionInfo.getQuestionType() == 61) {
            String quesBody = testQuestionInfo.getQuestionHTML();
            // 去掉<span>标签中的lang
            quesBody = replaceLang(quesBody);
            // 获取img标签
            LinkedHashMap<String, String> bodyImgList = imgList(quesBody);
            // 替换、补全Img标签
            quesBody = replaceImg(bodyImgList, quesBody);
            question.setQuesBody("<p>" + quesBody + "</p>");
            question.setQuesBodyWord(
                    DocxProcessUtil.html2Docx(wordMLPackage, CommonUtils.formatHtml(question.getQuesBody())));
            question.setQuestionType(QuesStructType.TEXT_ANSWER_QUESTION);
            String answer = testQuestionInfo.getAnswer();
            // 去掉<span>标签中的lang
            answer = replaceLang(answer);
            // 获取img标签
            LinkedHashMap<String, String> answerImgList = imgList(answer);
            // 替换、补全Img标签
            answer = replaceImg(answerImgList, answer);
            question.setQuesAnswer("<p>" + answer + "</p>");
            question.setQuesAnswerWord(
                    DocxProcessUtil.html2Docx(wordMLPackage, CommonUtils.formatHtml(question.getQuesAnswer())));
        }
        // 单选题
        if (testQuestionInfo.getQuestionType() == 11) {
            String quesBody = testQuestionInfo.getQuestionHTML();
            // 去掉<span>标签中的lang
            quesBody = replaceLang(quesBody);
            // 获取img标签
            LinkedHashMap<String, String> bodyImgList = imgList(quesBody);
            // 替换、补全Img标签
            quesBody = replaceImg(bodyImgList, quesBody);
            question.setQuesBody("<p>" + quesBody + "</p>");
            question.setQuesBodyWord(
                    DocxProcessUtil.html2Docx(wordMLPackage, CommonUtils.formatHtml(question.getQuesBody())));
            question.setQuestionType(QuesStructType.SINGLE_ANSWER_QUESTION);
            List<QuesOption> quesOptions = new ArrayList<QuesOption>();
            List<TestOption> options = testQuestionInfo.getOptions();
            Integer answerNumber = null;
            if (options != null && options.size() > 0) {
                int number = 1;
                short isCorrect = 0;
                for (TestOption testOption : options) {
                    if (testOption.getID().equals(testQuestionInfo.getAnswerId())) {
                        isCorrect = 1;
                        answerNumber = number;
                    } else {
                        isCorrect = 0;
                    }
                    QuesOption quesOption = initQuesOption(testOption, number, isCorrect, wordMLPackage);
                    quesOptions.add(quesOption);
                    number++;
                }
            }
            question.setQuesOptions(quesOptions);
            if (answerNumber != null) {
                char c1 = (char) (answerNumber + 64);
                question.setQuesAnswer(String.valueOf(c1));
                question.setQuesAnswerWord(DocxProcessUtil.html2Docx(wordMLPackage,
                        CommonUtils.formatHtml("<p>" + question.getQuesAnswer() + "</p>")));
            }
        }
        // 多选题
        if (testQuestionInfo.getQuestionType() == 12) {
            String quesBody = testQuestionInfo.getQuestionHTML();
            // 去掉<span>标签中的lang
            quesBody = replaceLang(quesBody);
            // 获取img标签
            LinkedHashMap<String, String> bodyImgList = imgList(quesBody);
            // 替换、补全Img标签
            quesBody = replaceImg(bodyImgList, quesBody);
            question.setQuesBody("<p>" + quesBody + "</p>");
            question.setQuesBodyWord(
                    DocxProcessUtil.html2Docx(wordMLPackage, CommonUtils.formatHtml(question.getQuesBody())));
            question.setQuestionType(QuesStructType.MULTIPLE_ANSWER_QUESTION);
            List<QuesOption> quesOptions = new ArrayList<QuesOption>();
            List<TestOption> options = testQuestionInfo.getOptions();
            List<Integer> answerNumbers = new ArrayList<Integer>();
            if (options != null && options.size() > 0) {
                int number = 1;
                short isCorrect = 0;
                for (TestOption testOption : options) {
                    if (testQuestionInfo.getAnswers().contains(testOption.getID())) {
                        isCorrect = 1;
                        answerNumbers.add(number);
                    } else {
                        isCorrect = 0;
                    }
                    QuesOption quesOption = initQuesOption(testOption, number, isCorrect, wordMLPackage);
                    quesOptions.add(quesOption);
                    number++;
                }
            }
            question.setQuesOptions(quesOptions);
            if (answerNumbers != null && answerNumbers.size() > 0) {
                String answers = "";
                for (Integer number : answerNumbers) {
                    char c1 = (char) (number + 64);
                    if (StringUtils.isBlank(answers)) {
                        answers = String.valueOf(c1);
                    } else {
                        answers = answers + "," + String.valueOf(c1);
                    }
                }
                question.setQuesAnswer(answers);
                question.setQuesAnswerWord(DocxProcessUtil.html2Docx(wordMLPackage,
                        CommonUtils.formatHtml("<p>" + question.getQuesAnswer() + "</p>")));
            }
        }
        // 填空题 ###
        if (testQuestionInfo.getQuestionType() == 13) {
            String quesBody = testQuestionInfo.getQuestionHTML();
            // 去掉<span>标签中的lang
            quesBody = replaceLang(quesBody);
            // 获取img标签
            LinkedHashMap<String, String> imgList = imgList(quesBody);
            if (imgList != null && imgList.size() > 0) {
                for (Map.Entry<String, String> entry : imgList.entrySet()) {
                    if (StringUtils.isBlank(entry.getValue())) {
                        quesBody = quesBody.replace(entry.getKey(), "(###)");
                    } else {
                        quesBody = quesBody.replace(entry.getKey(), entry.getValue());
                    }
                }
            }
            question.setQuesBody("<p>" + quesBody + "</p>");
            question.setQuesBodyWord(
                    DocxProcessUtil.html2Docx(wordMLPackage, CommonUtils.formatHtml(question.getQuesBody())));
            question.setQuestionType(QuesStructType.FILL_BLANK_QUESTION);
            String answer = "";
            List<TestFillAnswer> blanks = testQuestionInfo.getBlanks();
            if (blanks != null && blanks.size() > 0) {
                for (TestFillAnswer testFillAnswer : blanks) {
                    List<TestFillContent> answers = testFillAnswer.getAnswers();
                    if (answers != null && answers.size() > 0) {
                        for (TestFillContent testFillContent : answers) {
                            if (StringUtils.isBlank(answer)) {
                                answer = testFillContent.getContent();
                            } else {
                                answer = answer + "##" + testFillContent.getContent();
                            }
                        }
                    }
                }
                // 去掉<span>标签中的lang
                answer = replaceLang(answer);
                // 获取img标签
                LinkedHashMap<String, String> answerImgList = imgList(answer);
                // 替换、补全Img标签
                answer = replaceImg(answerImgList, answer);
                question.setQuesAnswer("<p>" + answer + "</p>");
                question.setQuesAnswerWord(
                        DocxProcessUtil.html2Docx(wordMLPackage, CommonUtils.formatHtml(question.getQuesAnswer())));
            }
        }
        // 判断题
        if (testQuestionInfo.getQuestionType() == 20) {
            String quesBody = testQuestionInfo.getQuestionHTML();
            // 去掉<span>标签中的lang
            quesBody = replaceLang(quesBody);
            // 获取img标签
            LinkedHashMap<String, String> bodyImgList = imgList(quesBody);
            // 替换、补全Img标签
            quesBody = replaceImg(bodyImgList, quesBody);
            question.setQuesBody("<p>" + quesBody + "</p>");
            question.setQuesBodyWord(
                    DocxProcessUtil.html2Docx(wordMLPackage, CommonUtils.formatHtml(question.getQuesBody())));
            question.setQuestionType(QuesStructType.BOOL_ANSWER_QUESTION);
            String answer = testQuestionInfo.getAnswer();
            if (answer.equals("false")) {
                answer = "错误";
            } else {
                answer = "正确";
            }
            question.setQuesAnswer(answer);
            question.setQuesAnswerWord(DocxProcessUtil.html2Docx(wordMLPackage,
                    CommonUtils.formatHtml("<p>" + question.getQuesAnswer() + "</p>")));
        }
        set.add(question);
    }

    // 去除<span> 标签中lang = EN - US
    private String replaceLang(String str) {
        if (str.contains("lang=EN-US")) {
            str = str.replace("lang=EN-US", "");
        }
        if (str.contains("alt=\"\u0012\"")) {
            str = str.replace("alt=\"\u0012\"", "alt=\"\"");
        }
        if (str.contains("alt=\"&#18;\"")) {
            str = str.replace("alt=\"&#18;\"", "alt=\"\"");
        }
        if (str.contains("\u000b")) {
            str = str.replaceAll("\u000b", "");
        }
        if (str.contains("&#0;")) {
            str = str.replaceAll("&#0;", "");
        }
        if (str.contains(
                "<img  width=\"25\" height=\"23\" src=\"/UploadFiles/Import/Image/3cf48167-932f-4ae6-be69-37520a02cd23_.png\"/>")) {
            str = str.replaceAll(
                    "<img  width=\"25\" height=\"23\" src=\"/UploadFiles/Import/Image/3cf48167-932f-4ae6-be69-37520a02cd23_.png\"/>",
                    "图片缺失");
        }
        if (str.contains(
                "<img  width=\"25\" height=\"23\" src=\"/UploadFiles/Import/Image/3cf48167-932f-4ae6-be69-37520a02cd23_.png\"/>")) {
            str = str.replaceAll(
                    "<img  width=\"25\" height=\"23\" src=\"/UploadFiles/Import/Image/3cf48167-932f-4ae6-be69-37520a02cd23_.png\"/>",
                    "图片缺失");
        }
        if (str.contains(
                "<img  width=\"24\" height=\"24\" src=\"/UploadFiles/Import/Image/811ae8b2-4d74-4cc2-a8a3-9665e5e810c1_.png\"/>")) {
            str = str.replaceAll(
                    "<img  width=\"24\" height=\"24\" src=\"/UploadFiles/Import/Image/811ae8b2-4d74-4cc2-a8a3-9665e5e810c1_.png\"/>",
                    "图片缺失");
        }
        if (str.contains("<img width=\"12\" height=\"13\" src=\"管理会计%20专升本.files/image001.png\">")) {
            str = str.replaceAll("<img width=\"12\" height=\"13\" src=\"管理会计%20专升本.files/image001.png\">", "图片缺失");
        }
        if (str.contains(
                "<img style=\"max-width: 600px; height: auto\" alt=\"\" src=\"/UploadFiles/刘晓平/Images/OnlineExam20180709151328.png\" />")) {
            str = str.replaceAll(
                    "<img style=\"max-width: 600px; height: auto\" alt=\"\" src=\"/UploadFiles/刘晓平/Images/OnlineExam20180709151328.png\" />",
                    "图片缺失");
        }
        if (str.contains("<img width=\"52\" height=\"45\" src=\"机械制造工艺学%20专升本%20综合测试2.files/image002.png\">")) {
            str = str.replaceAll("<img width=\"52\" height=\"45\" src=\"机械制造工艺学%20专升本%20综合测试2.files/image002.png\">",
                    "图片缺失");
        }
        if (str.contains(
                "<img  width=\"25\" height=\"23\" src=\"/UploadFiles/Import/Image/001d24f0-a007-4c13-8cb4-2a138d0545ae_.png\"/>")) {
            str = str.replaceAll(
                    "<img  width=\"25\" height=\"23\" src=\"/UploadFiles/Import/Image/001d24f0-a007-4c13-8cb4-2a138d0545ae_.png\"/>",
                    "图片缺失");
        }
        if (str.contains("<img src=\"/UploadFiles/李家林/Images/OnlineExam20140312164501.png\" alt=\"\" />")) {
            str = str.replaceAll("<img src=\"/UploadFiles/李家林/Images/OnlineExam20140312164501.png\" alt=\"\" />",
                    "图片缺失");
        }
        if (str.contains(
                "<img  width=\"25\" height=\"23\" src=\"/UploadFiles/Import/Image/001d24f0-a007-4c13-8cb4-2a138d0545ae_.png\"/>")) {
            str = str.replaceAll(
                    "<img  width=\"25\" height=\"23\" src=\"/UploadFiles/Import/Image/001d24f0-a007-4c13-8cb4-2a138d0545ae_.png\"/>",
                    "图片缺失");
        }
        if (str.contains(
                "<img  width=\"24\" height=\"24\" src=\"/UploadFiles/Import/Image/7828a9f0-5ec4-435d-ac78-cc400bc4cc22_.png\"/>")) {
            str = str.replaceAll(
                    "<img  width=\"24\" height=\"24\" src=\"/UploadFiles/Import/Image/7828a9f0-5ec4-435d-ac78-cc400bc4cc22_.png\"/>",
                    "图片缺失");
        }
        if (str.contains("<img alt=\"\" src=\"/UploadFiles/王建军/Images/OnlineExam20160319160348.jpg\" />")) {
            str = str.replaceAll("<img alt=\"\" src=\"/UploadFiles/王建军/Images/OnlineExam20160319160348.jpg\" />",
                    "图片缺失");
        }

        // if (str.contains("&lt;")) {
        // str = str.replace("&lt;", "<");
        // }
        // if (str.contains("&gt;")) {
        // str = str.replace("&gt;", ">");
        // }
        // if (str.contains("&")) {
        // str = str.replaceAll("&", "&amp;");
        // }
        // if (str.contains("<")) {
        // str = str.replaceAll("<", "&lt;");
        // }
        // if (str.contains(">")) {
        // str = str.replaceAll(">", "&gt;");
        // }
        return str;
    }

    // 替换img标签，补全图片
    private String replaceImg(LinkedHashMap<String, String> imgList, String str) {
        if (imgList != null && imgList.size() > 0) {
            for (Map.Entry<String, String> entry : imgList.entrySet()) {
                if (StringUtils.isBlank(entry.getValue())) {
                    str = str.replace(entry.getKey(), "___");
                } else {
                    str = str.replace(entry.getKey(), entry.getValue());
                }
            }
        }
        return str;
    }

    // 將url路徑中的中文转码
    private String regexCH(String str) throws UnsupportedEncodingException {
        StringBuffer s = new StringBuffer();
        Pattern pat = Pattern.compile("[\u4E00-\u9FA5]");
        Matcher mat = pat.matcher(str);
        while (mat.find()) {
            s.append(mat.group());
        }
        String url = URLEncoder.encode(s.toString(), "utf-8");
        return str.replace(s.toString(), url);
    }

    // 去除图片中有下划线的图片，并补全图片下载地址
    private LinkedHashMap<String, String> imgList(String str) throws Exception {
        LinkedHashMap<String, String> map = new LinkedHashMap<>();
        // 获取img标签
        List<String> srcList = ImgDataUtils.parseImages(str);
        if (srcList != null && srcList.size() > 0) {
            for (String img : srcList) {
                if (img.contains("/Shared/UnderLine")) {
                    map.put(img, "");
                } else {
                    List<String> parseImageSrc = ImgDataUtils.parseImageSrc(img);
                    if (parseImageSrc != null && parseImageSrc.size() > 0) {
                        String src = parseImageSrc.get(0);
                        String url = regexCH(src);
                        String picture = null;
                        if (url.startsWith("http://ncexam.cug.edu.cn/")) {
                            picture = url;
                        } else {
                            picture = "http://ncexam.cug.edu.cn" + url;
                        }
                        String base64 = ImgDataUtils.loadImageToBase64(picture);
                        if (base64 == null) {
                            throw new StatusException("50001", "图片下载失败" + picture);
                        } else {
                            if (src.contains("jpg")) {
                                map.put(img, img.replace(src, "data:image/jpg;base64," + base64));
                            } else if (src.contains("bmp")) {
                                map.put(img, img.replace(src, "data:image/bmp;base64," + base64));
                            } else {
                                map.put(img, img.replace(src, "data:image/png;base64," + base64));
                            }
                        }
                    }
                }
            }
            return map;
        }
        return null;
    }

    private List<Question> initSubQuestionsByOther(TestQuestionInfo testQuestionInfo,
            WordprocessingMLPackage wordMLPackage) throws Exception {
        List<Question> subQuestions = new ArrayList<Question>();
        if (testQuestionInfo.getBlanks() != null && testQuestionInfo.getBlanks().size() > 0) {
            List<TestFillAnswer> blanks = testQuestionInfo.getBlanks();
            for (TestFillAnswer testFillAnswer : blanks) {
                Question subQuestion = new Question();
                subQuestion.setId(new ObjectId().toString());
                subQuestion.setQuestionType(QuesStructType.SINGLE_ANSWER_QUESTION);
                subQuestion.setDifficulty("中");
                subQuestion.setDifficultyDegree(0.5);
                subQuestion.setPublicity(true);
                subQuestion.setQuesBody("______");
                subQuestion.setQuesBodyWord(DocxProcessUtil.html2Docx(wordMLPackage,
                        CommonUtils.formatHtml("<p>" + subQuestion.getQuesBody() + "</p>")));
                List<QuesOption> quesOptions = new ArrayList<QuesOption>();
                TestOptionGroup optionGroup = testQuestionInfo.getOptionGroup();
                List<TestOption> options = optionGroup.getOptions();
                Integer answerNumber = null;
                if (options != null && options.size() > 0) {
                    for (TestOption subOption : options) {
                        int subNumber = 1;
                        short isCorrect = 0;
                        if (testFillAnswer.getAnswerId().equals(subOption.getID())) {
                            isCorrect = 1;
                            answerNumber = subNumber;
                        } else {
                            isCorrect = 0;
                        }
                        QuesOption quesOption = initQuesOption(subOption, subNumber, isCorrect, wordMLPackage);
                        quesOptions.add(quesOption);
                        subNumber++;
                    }
                }
                subQuestion.setQuesOptions(quesOptions);
                if (answerNumber != null) {
                    char c1 = (char) (answerNumber + 64);
                    subQuestion.setQuesAnswer(String.valueOf(c1));
                    subQuestion.setQuesAnswerWord(DocxProcessUtil.html2Docx(wordMLPackage,
                            CommonUtils.formatHtml("<p>" + subQuestion.getQuesAnswer() + "</p>")));
                }
                subQuestions.add(subQuestion);
            }
        }
        return subQuestions;
    }

    // 初始化选项
    private QuesOption initQuesOption(TestOption testOption, int number, short isCorrect,
            WordprocessingMLPackage wordMLPackage) throws Exception {
        QuesOption quesOption = new QuesOption();
        quesOption.setNumber(String.valueOf(number));
        quesOption.setIsCorrect(isCorrect);
        String optionBody = testOption.getOptionHTML();
        // 去掉<span>标签中的lang
        optionBody = replaceLang(optionBody);
        // 获取img标签
        LinkedHashMap<String, String> optionBodyImgList = imgList(optionBody);
        // 替换、补全Img标签
        optionBody = replaceImg(optionBodyImgList, optionBody);
        quesOption.setOptionBody("<p>" + optionBody + "</p>");
        quesOption.setOptionBodyWord(
                DocxProcessUtil.html2Docx(wordMLPackage, CommonUtils.formatHtml(quesOption.getOptionBody())));
        return quesOption;
    }

    // 根据父ID查询子题
    private List<TestQuestion> querySubQuestions(String parentId, String dir, XSSFSheet sheet) {
        List<TestQuestion> questions = new ArrayList<TestQuestion>();
        for (int i = 1; i <= sheet.getLastRowNum(); i++) {
            XSSFRow row = sheet.getRow(i);
            String pid = row.getCell(5).getStringCellValue();
            if (parentId.equals(pid)) {
                TestQuestion tq = new TestQuestion();
                tq.setId(row.getCell(0).getStringCellValue());
                tq.setdNumber(getIntByString(row.getCell(1).getStringCellValue()));
                tq.setdName(row.getCell(2).getStringCellValue());
                tq.setNumber(getIntByString(row.getCell(3).getStringCellValue()));
                tq.setScore(getDoubleByString(row.getCell(4).getStringCellValue()));
                tq.setParentId(row.getCell(5).getStringCellValue());
                tq.setType(getIntByString(row.getCell(6).getStringCellValue()));
                File quesJson = new File(dir + tq.getId() + ".txt");
                if (!quesJson.exists()) {
                    throw new StatusException("400002", "试题信息文件不存在");
                }
                tq.setJson(FileUtil.readFileContent(quesJson));
                questions.add(tq);
            }
        }

        if (questions.size() == 0) {
            throw new StatusException("400001", "试题信息为空");
        }
        return questions;
    }

    // 完形填空初始化所有子题
    private List<Question> initSubQuestions(List<TestFillAnswer> blanks, WordprocessingMLPackage wordMLPackage)
            throws Exception {
        List<Question> subQuestions = new ArrayList<Question>();
        if (blanks != null && blanks.size() > 0) {
            for (TestFillAnswer testFillAnswer : blanks) {
                Question question = new Question();
                question.setId(new ObjectId().toString());
                question.setQuestionType(QuesStructType.SINGLE_ANSWER_QUESTION);
                question.setDifficulty("中");
                question.setDifficultyDegree(0.5);
                question.setPublicity(true);
                question.setQuesBody("______");
                question.setQuesBodyWord(DocxProcessUtil.html2Docx(wordMLPackage,
                        CommonUtils.formatHtml("<p>" + question.getQuesBody() + "</p>")));
                TestOptionGroup optionGroup = testFillAnswer.getOptionGroup();
                List<QuesOption> quesOptions = new ArrayList<QuesOption>();
                List<TestOption> subOptions = optionGroup.getOptions();
                Integer answerNumber = null;
                if (subOptions != null && subOptions.size() > 0) {
                    int subNumber = 1;
                    short isCorrect = 0;
                    for (TestOption subOption : subOptions) {
                        if (testFillAnswer.getAnswerId().equals(subOption.getID())) {
                            isCorrect = 1;
                            answerNumber = subNumber;
                        } else {
                            isCorrect = 0;
                        }
                        QuesOption quesOption = initQuesOption(subOption, subNumber, isCorrect, wordMLPackage);
                        quesOptions.add(quesOption);
                        subNumber++;
                    }
                }
                question.setQuesOptions(quesOptions);
                if (answerNumber != null) {
                    char c1 = (char) (answerNumber + 64);
                    question.setQuesAnswer(String.valueOf(c1));
                    question.setQuesAnswerWord(DocxProcessUtil.html2Docx(wordMLPackage,
                            CommonUtils.formatHtml("<p>" + question.getQuesAnswer() + "</p>")));
                }
                subQuestions.add(question);
            }
        }
        return subQuestions;
    }

    // 初始化小题对象
    private PaperDetailUnit initPaperDetailUnit(Paper paper, PaperDetail paperDetail, Question question,
            TestQuestion testQuestion, User user) {
        PaperDetailUnit paperDetailUnit = new PaperDetailUnit();
        paperDetailUnit.setPaper(paper);
        paperDetailUnit.setNumber(testQuestion.getNumber());
        paperDetailUnit.setScore(testQuestion.getScore());
        paperDetailUnit.setPaperDetail(paperDetail);
        paperDetailUnit.setQuestionType(question.getQuestionType());
        paperDetailUnit.setCreator(user.getDisplayName());
        paperDetailUnit.setCreateTime(CommonUtils.getCurDateTime());
        paperDetailUnit.setQuestion(question);
        paperDetailUnit.setPaperType(PaperType.IMPORT);
        return paperDetailUnit;
    }
}
