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

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.servlet.http.HttpServletResponse;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.stereotype.Service;

import com.google.common.collect.Lists;
import com.google.gson.Gson;

import cn.com.qmth.examcloud.api.commons.enums.AdminOperateType;
import cn.com.qmth.examcloud.api.commons.security.bean.User;
import cn.com.qmth.examcloud.commons.exception.StatusException;
import cn.com.qmth.examcloud.core.questions.base.CommonUtils;
import cn.com.qmth.examcloud.core.questions.base.FileDisposeUtil;
import cn.com.qmth.examcloud.core.questions.base.IdUtils;
import cn.com.qmth.examcloud.core.questions.base.Model;
import cn.com.qmth.examcloud.core.questions.base.converter.utils.FileUtil;
import cn.com.qmth.examcloud.core.questions.base.enums.ExamFileType;
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.CoursePropertyRepo;
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.QuestionAudioRepo;
import cn.com.qmth.examcloud.core.questions.dao.entity.Course;
import cn.com.qmth.examcloud.core.questions.dao.entity.CourseProperty;
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.Property;
import cn.com.qmth.examcloud.core.questions.dao.entity.QuesOption;
import cn.com.qmth.examcloud.core.questions.dao.entity.QuesProperty;
import cn.com.qmth.examcloud.core.questions.dao.entity.Question;
import cn.com.qmth.examcloud.core.questions.dao.entity.QuestionAudio;
import cn.com.qmth.examcloud.core.questions.dao.entity.computerTestModel.Block;
import cn.com.qmth.examcloud.core.questions.dao.entity.computerTestModel.ComputerTestOption;
import cn.com.qmth.examcloud.core.questions.dao.entity.computerTestModel.ComputerTestPaper;
import cn.com.qmth.examcloud.core.questions.dao.entity.computerTestModel.ComputerTestPaperDetail;
import cn.com.qmth.examcloud.core.questions.dao.entity.computerTestModel.ComputerTestQuestion;
import cn.com.qmth.examcloud.core.questions.dao.entity.computerTestModel.Section;
import cn.com.qmth.examcloud.core.questions.dao.entity.computerTestModel.Sections;
import cn.com.qmth.examcloud.core.questions.service.ExportPaperService;
import cn.com.qmth.examcloud.core.questions.service.ExportThemisPaperService;
import cn.com.qmth.examcloud.core.questions.service.PaperDetailService;
import cn.com.qmth.examcloud.core.questions.service.PaperService;
import cn.com.qmth.examcloud.core.questions.service.PropertyService;
import cn.com.qmth.examcloud.core.questions.service.bean.dto.DownloadPaperDto;
import cn.com.qmth.examcloud.core.questions.service.bean.dto.PaperExp;
import cn.com.qmth.examcloud.core.questions.service.bean.dto.QuestionDistributeDto;
import cn.com.qmth.examcloud.core.questions.service.converter.PrintExamPaperService;
import cn.com.qmth.examcloud.core.questions.service.export.ExportPaperAbstractService;
import cn.com.qmth.examcloud.core.questions.service.themispaper.ThemisPaperAndAnswer;
import cn.com.qmth.examcloud.core.questions.service.util.ExportPaperUtil;
import cn.com.qmth.examcloud.core.questions.service.util.PaperUtil;
import cn.com.qmth.examcloud.reports.commons.bean.AdminOperateReport;
import cn.com.qmth.examcloud.reports.commons.util.ReportsUtil;
import cn.com.qmth.examcloud.support.filestorage.FileStorageUtil;

@Service("exportPaperService")
public class ExportPaperServiceImpl implements ExportPaperService {

    private static final Logger LOG = LoggerFactory.getLogger(ExportPaperServiceImpl.class);

    public static final String TEMP_FILE_EXP = "docxExport/";

    public static final String TEMP_FILE_NAME = "_考试说明.docx";

    public static final String DOCX_SUFFIX = ".docx";

    public static final String ZIP_SUFFIX = ".zip";

    @Autowired
    private PaperRepo paperRepo;

    @Autowired
    private PaperService paperService;

    @Autowired
    private PaperDetailService paperDetailService;

    @Autowired
    private MongoTemplate mongoTemplate;

    @Autowired
    private CoursePropertyRepo coursePropertyRepo;

    @Autowired
    private PropertyService propertyService;

    @Autowired
    private QuestionAudioRepo questionAudioRepo;

    @Autowired
    private PrintExamPaperService printExamPaperService;

    @Autowired
    private PaperDetailUnitRepo paperDetailUnitRepo;
    
    @Autowired
    private ExportThemisPaperService exportThemisPaperService;

//    @Autowired
//    protected QuesPkgPathRepo quesPkgPathRepo;

//    @Autowired
//    private SysProperty sysProperty;
    @Override
    public void exportPaperFile(String paperId, String exportContentList,
            HttpServletResponse response, PaperSeqMode seqMode, String examType, String psw, User user) {
        ExportPaperAbstractService exportPaperAbstractService = PaperUtil.getByRootOrgId(user.getRootOrgId().toString());
        // 根据试卷id查询试卷
        Paper paper = Model.of(paperRepo.findById(paperId));

        String zipFileName =IdUtils.uuid();
        long startTime;
        try {
            File directory = new File(TEMP_FILE_EXP + File.separator + zipFileName);
            if (!directory.exists()) {
                directory.mkdirs();
            }
            if (exportContentList.indexOf(ExamFileType.PRINT_EXAM_PACKAGE.name()) > -1) {
                printExamPaperService.downloadPaper(Lists.newArrayList(paper), directory.getAbsolutePath(), psw);
            }
            if (exportContentList.indexOf(ExamFileType.COMPUTERTEST_PACKAGE.name()) > -1) {
                downJson(paper, zipFileName);
            }
            if (exportContentList.indexOf(ExamFileType.THEMIS_PACKAGE.name()) > -1) {
            	List<Paper> papers=new ArrayList<>();
            	papers.add(paper);
                downThemisPackage(papers, zipFileName);
            }
            try {
            	DownloadPaperDto dto=new DownloadPaperDto(user.getRootOrgId(), paperId, zipFileName, examType,seqMode);
                if (exportContentList.indexOf(ExamFileType.PAPER.name()) > -1) {
                    exportPaperAbstractService.downloadPaper(dto);
                }

                if (exportContentList.indexOf(ExamFileType.ANSWER.name()) > -1) {
                    exportPaperAbstractService.downloadPaperAnswer(dto);
                }
            } catch (StatusException e) {
                LOG.error(e.getMessage(), e);
                throw e;
            } catch (Exception e) {
                LOG.error(e.getMessage(), e);
                throw new StatusException("100001", e.getMessage());
            }
            // 下载考试说明 2018-2-27 weiwehai
            /*
             * if(examType.equals("offLine") &&
             * StringUtils.isNotBlank(paper.getExamRemark())){
             * downExamRemark(paper,zipFileName); }
             */
            LOG.debug("开始压缩成zip...");
            startTime = System.currentTimeMillis();
            FileDisposeUtil.fileToZip(TEMP_FILE_EXP + File.separator + zipFileName, TEMP_FILE_EXP, zipFileName);
            FileDisposeUtil.downloadFile(paper.getName() + "_" + paper.getCourse().getCode() + ".zip",
                    TEMP_FILE_EXP + File.separator + zipFileName + ".zip", response);
            long endTime = System.currentTimeMillis();
            LOG.debug("下载zip耗时:" + (endTime - startTime) + "ms");
        } finally {
            long endTime = System.currentTimeMillis();
			FileUtil.deleteFolder(TEMP_FILE_EXP+ File.separator + zipFileName);
			FileUtil.deleteFolder(TEMP_FILE_EXP+ File.separator + zipFileName+ ".zip");
//            deteleFolder(TEMP_FILE_EXP, zipFileName);
            long deleteTime = System.currentTimeMillis();
            LOG.debug("删除文件耗时:" + (deleteTime - endTime) + "ms");
        }
        StringBuilder paperInfo=new StringBuilder();
		paperInfo.append("课程:"+paper.getCourse().getName()+"("+paper.getCourse().getCode()+")");
		paperInfo.append(" 试卷名称:"+paper.getName());
		paperInfo.append(getContentName(exportContentList));
		
		ReportsUtil.report(new AdminOperateReport(user.getRootOrgId(), user.getUserId(), AdminOperateType.TYPE36.getDesc(),paperInfo.toString()));
    }

    private String getContentName(String exportContentList) {
    	StringBuilder sb=new StringBuilder();
    	sb.append(" 下载内容:");
    	for(String content:exportContentList.split(",")) {
    		sb.append(ExamFileType.valueOf(content).getName()+",");
    	}
    	sb.deleteCharAt(sb.length()-1);
    	return sb.toString();
    }
    /**
     * 下载考试说明
     *
     * @param zipFileName
     * @throws Exception
     */
//    @SuppressWarnings("unused")
//    private void downExamRemark(Paper paper, String zipFileName) throws Exception {
//        // 1.考试说明html转成word
//        String title = "<p style=\"text-align:center\"><span style=\"font-size:26px\"><span style=\"font-family:宋体\">考&nbsp;试&nbsp;说&nbsp;明</span></span></p>";
//        WordprocessingMLPackage wordMLPackage = WordprocessingMLPackage.createPackage();
//        DocxProcessUtil.html2Docx(wordMLPackage, CommonUtils.formatHtml(title + paper.getExamRemark()));
//        // 2.导出考试说明word
//        File file = new File(TEMP_FILE_EXP + File.separator + zipFileName + File.separator + paper.getCourse().getCode()
//                + TEMP_FILE_NAME);
//        Docx4J.save(wordMLPackage, file);
//    }

//    private void deteleFolder(String sourceFilePath, String zipFileName) {
//        File ComputerTestPaperfoler = new File(sourceFilePath + File.separator + "json");
//        if (ComputerTestPaperfoler.exists()) {
//            FileUtils.deleteQuietly(ComputerTestPaperfoler);
//        }
//        File zipFolder = new File(sourceFilePath + File.separator + zipFileName);
//        if (zipFolder.exists()) {
//            FileUtils.deleteQuietly(zipFolder);
//        }
//        File zipFile = new File(sourceFilePath + File.separator + zipFileName + ".zip");
//        if (zipFile.exists()) {
//            FileUtils.deleteQuietly(zipFile);
//        }
//    }

    private void downJson(Paper paper, String zipFileName) {
        ComputerTestPaper computerTestPaper = buildComputerTestPapers(paper);
        String jsonDirectory = TEMP_FILE_EXP + File.separator+zipFileName+File.separator + "json";
        try {
	        // 新建文件夹
	        File dirFile = new File(jsonDirectory);
	        if (!dirFile.exists()) {
	            dirFile.mkdirs();
	        }
	        makeComputerTestPaperToJsonFile(paper.getCourse().getCode(), computerTestPaper, jsonDirectory);
	        downloadAudio(computerTestPaper, jsonDirectory);
	        // 将文件夹打包成zip压缩包放在docxExport下
	        FileDisposeUtil.fileToZip(jsonDirectory, TEMP_FILE_EXP + File.separator + zipFileName,
	                paper.getCourse().getCode() + "_" + paper.getName());
		} finally {
			FileUtil.deleteDirectory(jsonDirectory);
		}
    }
    
    private void downThemisPackage(List<Paper> papers, String zipFileName) {
        String zipDirectory = TEMP_FILE_EXP + File.separator +zipFileName+ File.separator+ "themis_package";
        // 新建文件夹
        File dirFile = new File(zipDirectory);
        if (!dirFile.exists()) {
        	dirFile.mkdirs();
        }
        try {
        	for(Paper paper:papers) {
        		ThemisPaperAndAnswer pa = exportThemisPaperService.buildPaperAndAnswer(paper);
				String paperDirectory = zipDirectory + File.separator + paper.getCourseNo() + File.separator
						+ paper.getId();
				File paperDir = new File(paperDirectory);
				if (!paperDir.exists()) {
					paperDir.mkdirs();
				}
				exportThemisPaperService.makePaperAnswerToJsonFile(pa, paperDirectory);
				exportThemisPaperService.downloadAudio(pa.getPaper(), paperDirectory);
        	}
			// 将文件夹打包成zip压缩包放在docxExport下
			File zipFile=new File(TEMP_FILE_EXP + File.separator + zipFileName+ File.separator + "在线考试数据包.zip");
			FileUtil.doZip(dirFile, zipFile);
		} finally {
			FileUtil.deleteDirectory(zipDirectory);
		}
    }

    private void downloadAudio(ComputerTestPaper computerTestPaper, String jsonDirectory) {
        // 取到所有大题
        List<ComputerTestPaperDetail> details = computerTestPaper.getDetails();
        if (details != null && details.size() > 0) {
            for (ComputerTestPaperDetail detail : details) {
                // 取到所有小题集合
                List<ComputerTestQuestion> questions = detail.getQuestions();
                if (questions != null && questions.size() > 0) {
                    for (ComputerTestQuestion question : questions) {
                        int bodyNum = 1;
                        // 取到题干
                        Sections body = question.getBody();
                        List<Section> sections = body.getSections();
                        for (Section section : sections) {
                            List<Block> blocks = section.getBlocks();
                            if (blocks != null && blocks.size() > 0) {
                                for (Block block : blocks) {
                                    if (block.getType().equals("audio")) {
                                        String id = block.getValue();
                                        QuestionAudio questionAudio = Model.of(questionAudioRepo.findById(id));
                                        String audioFileName = questionAudio.getId() + "_" + detail.getNumber() + "_"
                                                + question.getNumber() + "_1_" + bodyNum + "."
                                                + questionAudio.getFileSuffixes();
//                                        UpYun upyun = new UpYun(sysProperty.getBucketName(), sysProperty.getUserName(),
//                                                sysProperty.getPassword());
                                        File file = new File(jsonDirectory + File.separator + audioFileName);
//                                        upyun.readFile(questionAudio.getFileUrl(), file);
                                        //通用存储
    									FileStorageUtil.saveUrlAs(FileStorageUtil.realPath(questionAudio.getFileUrl()), file);
                                        bodyNum++;
                                    }
                                }
                            }
                        }
                        // 取到选项
                        List<ComputerTestOption> options = question.getOptions();
                        if (options != null && options.size() > 0) {
                            for (ComputerTestOption computerTestOption : options) {
                                int optionNum = 1;
                                // 获取选项主体
                                Sections optionBody = computerTestOption.getBody();
                                List<Section> optionSections = optionBody.getSections();
                                if (optionSections != null && optionSections.size() > 0) {
                                    for (Section optionSection : optionSections) {
                                        List<Block> blocks = optionSection.getBlocks();
                                        if (blocks != null && blocks.size() > 0) {
                                            for (Block block : blocks) {
                                                if (block.getType().equals("audio")) {
                                                    String id = block.getValue();
                                                    QuestionAudio questionAudio = Model
                                                            .of(questionAudioRepo.findById(id));
                                                    String audioFileName = questionAudio.getId() + "_"
                                                            + detail.getNumber() + "_" + question.getNumber() + "_2_"
                                                            + computerTestOption.getNumber() + "_" + optionNum + "."
                                                            + questionAudio.getFileSuffixes();
//                                                    UpYun upyun = new UpYun(sysProperty.getBucketName(),
//                                                            sysProperty.getUserName(), sysProperty.getPassword());
                                                    File file = new File(
                                                            jsonDirectory + File.separator + audioFileName);
//                                                    upyun.readFile(questionAudio.getFileUrl(), file);
                                                    //通用存储
                									FileStorageUtil.saveUrlAs(FileStorageUtil.realPath(questionAudio.getFileUrl()), file);
                                                    optionNum++;
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }

    /**
     * 构建机考数据包实体类
     *
     * @return
     */
    public ComputerTestPaper buildComputerTestPapers(Paper paper) {
        // 得到所有旧对象的大题对象
        List<PaperDetail> paperDetails = paperService.findPaperDetailsById(paper.getId());
        // 通过 paper 对象 ，生成新的 ComputerTestPaper 对象
        ComputerTestPaper computerTestPaper = new ComputerTestPaper(paper, "");
        List<ComputerTestPaperDetail> details = new ArrayList<>();
        // 遍历所有旧大题对象，得到小题对象的集合
        for (PaperDetail paperDetail : paperDetails) {
            List<PaperDetailUnit> paperDetailUnits = paperDetailService.getUnitsByPaperDetailId(paperDetail.getId());
            ComputerTestPaperDetail computerTestPaperDetail = new ComputerTestPaperDetail(paperDetail);
            List<ComputerTestQuestion> questions = new ArrayList<>();
            // 遍历所有的小题对象
            for (int i = 0; i < paperDetailUnits.size(); i++) {
                PaperDetailUnit paperDetailUnit = paperDetailUnits.get(i);
                // 根据旧的小题对象，生成新的小题对象
                ComputerTestQuestion computerTestQuestion = new ComputerTestQuestion(paperDetailUnit);
                // 设置小题题号
                computerTestQuestion.setNumber(i + 1);
                // 得到小题题干
                computerTestQuestion
                        .setBody(getBodyOrAnswer(paperDetailUnit.getQuestion().getQuesBody(), computerTestPaper));
                // 得到小题所有选项
                computerTestQuestion.setOptions(getOption(paperDetailUnit.getQuestion(), computerTestPaper));
                // 得到小题的答案
                computerTestQuestion
                        .setAnswer(getBodyOrAnswer(paperDetailUnit.getQuestion().getQuesAnswer(), computerTestPaper));
                // 查询小题中的 套题
                List<Question> subQuestionsList = paperDetailUnit.getQuestion().getSubQuestions();
                // 判断这个小题中是否有套题
                if (subQuestionsList != null && subQuestionsList.size() > 0) {
                    List<ComputerTestQuestion> subQuestions = new ArrayList<>();
                    // 遍历每个套题
                    for (int j = 0; j < subQuestionsList.size(); j++) {
                        Question subQuestion = subQuestionsList.get(j);
                        ComputerTestQuestion subcomputerTestQuestion = new ComputerTestQuestion(subQuestion);
                        // 设置套题中小题题号
                        subcomputerTestQuestion.setNumber(j + 1);
                        subcomputerTestQuestion.setBody(getBodyOrAnswer(subQuestion.getQuesBody(), computerTestPaper));
                        subcomputerTestQuestion.setOptions(getOption(subQuestion, computerTestPaper));
                        subcomputerTestQuestion
                                .setAnswer(getBodyOrAnswer(subQuestion.getQuesAnswer(), computerTestPaper));
                        subQuestions.add(subcomputerTestQuestion);
                    }
                    computerTestQuestion.setSubQuestions(subQuestions);
                }
                questions.add(computerTestQuestion);
            }
            computerTestPaperDetail.setQuestions(questions);
            // paperDetail中的题数(unitCount)可能不准确，这里以questions的实际size为准
            computerTestPaperDetail.setQuestionCount(questions.size());
            details.add(computerTestPaperDetail);
        }
        computerTestPaper.setDetails(details);
        return computerTestPaper;
    }

    private Sections getBodyOrAnswer(String str, ComputerTestPaper computerTestPaper) {
        Sections body = new Sections();
        List<Section> sections = new ArrayList<>();
        // 得到小题题干或者答案行数
        if (StringUtils.isBlank(str)) {
            return body;
        }
        String[] questionRowStrings = str.split("</p>");
        for (int i = 0; i < questionRowStrings.length; i++) {
            List<Block> blocks = disposeQuestionBodyOrOption(questionRowStrings[i], computerTestPaper);
            if (blocks != null && blocks.size() > 0) {
                Section section = new Section();
                // 将小题题干拆分为Block集合
                section.setBlocks(blocks);
                sections.add(section);
            }
        }
        body.setSections(sections);
        return body;
    }

    private List<ComputerTestOption> getOption(Question question, ComputerTestPaper computerTestPaper) {
        // 得到小题选项
        List<QuesOption> quesOptions = question.getQuesOptions();
        List<ComputerTestOption> options = new ArrayList<>();
        // 遍历小题选项
        if (quesOptions != null && quesOptions.size() > 0) {
            for (QuesOption quesOption : quesOptions) {
                ComputerTestOption option = new ComputerTestOption();
                option.setNumber(new Integer(quesOption.getNumber()));
                option.setCorrect(quesOption.getIsCorrect() == 1 ? true : false);
                Sections body = new Sections();

                List<Section> sections = new ArrayList<>();
                // 得到小题选项
                String optionString = quesOption.getOptionBody();
                String[] optionStrings = optionString.split("</p>");
                for (int i = 0; i < optionStrings.length; i++) {
                    List<Block> blocks = disposeQuestionBodyOrOption(optionStrings[i], computerTestPaper);
                    if (blocks != null && blocks.size() > 0) {
                        Section section = new Section();
                        section.setBlocks(blocks);
                        sections.add(section);
                    }
                }
                body.setSections(sections);
                option.setBody(body);
                options.add(option);
            }
        }
        return options;
    }

    private List<Block> disposeQuestionBodyOrOption(String questionRow, ComputerTestPaper computerTestPaper) {
        List<Block> blocks = new ArrayList<>();
        // 去掉每行里面的<p>,<span>,</span>标签
        questionRow = questionRow.replaceAll("<p>", "").replaceAll("</p>", "").replaceAll("<span>", "")
                .replaceAll("</span>", "").replaceAll("</a>", "");
        String[] questionRowStrings = questionRow.split("<|/>|>");
        boolean hasAudio = false;
        for (int i = 0; i < questionRowStrings.length; i++) {
            Block block = new Block();
            String rowStr = questionRowStrings[i];
            // 判断是否有图片
            if (rowStr.startsWith("img")) {
                rowStr = "<" + rowStr + ">";
                Map<String, Object> param = new HashMap<>();
                // 需要继续做截取，取到Parma
                block.setType("image");
                // 获取图片的路径
                List<String> strSrcList = getImg(rowStr, "src");
                if (strSrcList.size() > 0) {
                    String strSrc = strSrcList.get(0).replaceAll("src=\"", "").replaceAll("\"", "");
                    block.setValue(strSrc);
                }
                // 获取图片的高度
                List<String> strHeightList = getImg(rowStr, "height");
                if (strHeightList.size() > 0) {
                    String strHeight = strHeightList.get(0).replaceAll("height=\"", "").replaceAll("\"", "");
                    param.put("height", strHeight);
                }
                // 获取图片的宽度
                List<String> strWidthList = getImg(rowStr, "width");
                if (strHeightList.size() > 0) {
                    String strWidth = strWidthList.get(0).replaceAll("width=\"", "").replaceAll("\"", "");
                    param.put("width", strWidth);
                }
                block.setParam(param);
                blocks.add(block);
            } else if (rowStr.startsWith("a") && rowStr.contains("id") && rowStr.contains("name")) { // 处理音频
                rowStr = "<" + rowStr + ">";
                block.setPlayTime(1);
                block.setType("audio");
                block.setValue(CommonUtils.getAttrValue(rowStr, "id"));
                blocks.add(block);
                hasAudio = true;
            } else {
                block.setType("text");
                rowStr = rowStr.replace("&nbsp;", "");// 消除空格
                rowStr = rowStr.replace("&quot;", "\"");// 将&quot;转换成\"
                rowStr = rowStr.replace("&lt;", "<");// 将&lt;转换成<
                rowStr = rowStr.replace("&gt;", ">");// 将&gt;转换成>
                rowStr = rowStr.replace("&amp;", "&");// 将&amp;转换成&
                if (StringUtils.isNotBlank(rowStr)) {
                    block.setValue(rowStr);
                    blocks.add(block);
                }
            }
        }
        if (hasAudio) {
            computerTestPaper.setHasVideo(1);
        }
        return blocks;
    }

    /**
     * 获取图片里面的路径，长度，宽度
     */
    private List<String> getImg(String s, String str) {
        String regex;
        List<String> list = new ArrayList<>();
        regex = str + "=\"(.*?)\"";
        Pattern pa = Pattern.compile(regex, Pattern.DOTALL);
        Matcher ma = pa.matcher(s);
        while (ma.find()) {
            list.add(ma.group());
        }
        return list;
    }

    /**
     * 将computerTestPaper对象生成JSON文件存放在jsonDirectoryPath中
     *
     * @param computerTestPaper
     * @param jsonDirectoryPath
     */
    @SuppressWarnings("deprecation")
	private void makeComputerTestPaperToJsonFile(String courseCode, ComputerTestPaper computerTestPaper,
            String jsonDirectoryPath) {
        // 创建新的JSON文件
        File file = new File(jsonDirectoryPath + File.separator + courseCode + ".json");
        // 将对象转成 json对象
        Gson gson = new Gson();
        String strJSON = gson.toJson(computerTestPaper);

        strJSON = CommonUtils.replaceUnicodeStr(strJSON);
        // 生成文件流写入JSON文件
        FileOutputStream outputStream = null;
        try {
            outputStream = new FileOutputStream(file);
            byte b[] = strJSON.getBytes();
            outputStream.write(b);
            outputStream.flush();
        } catch (FileNotFoundException e) {
            LOG.error(e.getMessage(), e);
        } catch (IOException e) {
            LOG.error(e.getMessage(), e);
        } finally {
            IOUtils.closeQuietly(outputStream);
        }
    }

    @Override
    public void exportPaperFiles(List<String> paperIds, String exportContentList,
            HttpServletResponse response, PaperSeqMode seqMode, String examType, User user) throws Exception {
        ExportPaperAbstractService exportPaperAbstractService = PaperUtil.getByRootOrgId(user.getRootOrgId().toString());
        // 根据试卷id查询所有试卷
        List<Paper> papers = CommonUtils.toList(paperRepo.findByIdIn(paperIds));
        String zipFileName = IdUtils.uuid();
        try {
			// 创建压缩文件夹
			File directory = new File(TEMP_FILE_EXP + File.separator + zipFileName);
			directory.mkdirs();
			// 下载试卷
			if (exportContentList.indexOf(ExamFileType.PAPER.name()) > -1) {
				for (Paper paper : papers) {
					DownloadPaperDto dto=new DownloadPaperDto(user.getRootOrgId(), paper.getId(), zipFileName, examType,seqMode);
					exportPaperAbstractService.downloadPaper(dto);
				}
			}
			// 下载答案
			if (exportContentList.indexOf(ExamFileType.ANSWER.name()) > -1) {
				for (Paper paper : papers) {
					DownloadPaperDto dto=new DownloadPaperDto(user.getRootOrgId(), paper.getId(), zipFileName, examType,seqMode);
					exportPaperAbstractService.downloadPaperAnswer(dto);
				}
			}
			// 下载机考数据包
			if (exportContentList.indexOf(ExamFileType.COMPUTERTEST_PACKAGE.name()) > -1) {
				for (Paper paper : papers) {
					downJson(paper, zipFileName);
				}
			}
			// 下载在线考试数据包
			if (exportContentList.indexOf(ExamFileType.THEMIS_PACKAGE.name()) > -1) {
				downThemisPackage(papers, zipFileName);
			}
			FileDisposeUtil.fileToZip(TEMP_FILE_EXP + File.separator + zipFileName, TEMP_FILE_EXP, zipFileName);
			FileDisposeUtil.downloadFile(zipFileName + ".zip", TEMP_FILE_EXP + File.separator + zipFileName + ".zip",
					response);
		} finally {
			FileUtil.deleteFolder(TEMP_FILE_EXP+ File.separator + zipFileName);
			FileUtil.deleteFolder(TEMP_FILE_EXP+ File.separator + zipFileName+ ".zip");
		}
        StringBuilder paperInfo=new StringBuilder();
		paperInfo.append("下载数量:"+paperIds.size());
		paperInfo.append(getContentName(exportContentList));
		
		ReportsUtil.report(new AdminOperateReport(user.getRootOrgId(), user.getUserId(), AdminOperateType.TYPE37.getDesc(),paperInfo.toString()));
    
    }

    @Override
    public void downQuestionDistribute(String courseCode, HttpServletResponse response) throws IOException {
        // 生成导出Excle的list集合
        List<QuestionDistributeDto> questionDistributes = this.downQuestionDistribute(courseCode);

        final String fileName = courseCode + "试题分布.xlsx";
        final String filePath = TEMP_FILE_EXP + File.separator + fileName;

        // 生成Excel导出
        File tempFile = this.writeExcel(questionDistributes, filePath);
        FileDisposeUtil.downloadFile(fileName, filePath, response);
        FileUtils.deleteQuietly(tempFile);
    }

    @Override
    public void downQuestionDistributes(List<Course> courses) throws IOException {
        if (CollectionUtils.isEmpty(courses)) {
            return;
        }

        for (Course course : courses) {
            List<QuestionDistributeDto> questionDistributes = this.downQuestionDistribute(course.getCode());
            final String fileName = course.getCode() + "试题分布.xlsx";
            final String filePath = TEMP_FILE_EXP + File.separator + fileName;
            this.writeExcel(questionDistributes, filePath);
        }
    }

    private List<QuestionDistributeDto> downQuestionDistribute(String courseCode) {
        // 1.生成导出Excle的list集合
        List<QuestionDistributeDto> questionDistributes = new ArrayList<>();

        // 2.根据课程code查询课程属性集合
        List<CourseProperty> courseProperties = coursePropertyRepo.findByCourseCodeAndEnable(courseCode, true);
        if (CollectionUtils.isEmpty(courseProperties)) {
            return questionDistributes;
        }

        // 3.遍历课程属性集合，根据课程属性查询一级
        for (CourseProperty courseProperty : courseProperties) {
            List<Property> parentProperties = propertyService.findParentProperties(courseProperty.getId(),
                    courseProperty.getOrgId());
            if (parentProperties != null && parentProperties.size() > 0) {
                for (Property parentProperty : parentProperties) {
                    List<Property> sonProperties = propertyService.findSonProperties(parentProperty.getId());
                    if (sonProperties != null && sonProperties.size() > 0) {
                        for (Property sonProperty : sonProperties) {
                            // 单选题集合
                            List<Question> sinList = questionList(courseCode, courseProperty,
                                    QuesStructType.SINGLE_ANSWER_QUESTION, parentProperty, sonProperty);
                            // 多选题集合
                            List<Question> mulList = questionList(courseCode, courseProperty,
                                    QuesStructType.MULTIPLE_ANSWER_QUESTION, parentProperty, sonProperty);
                            // 判断题集合
                            List<Question> bolList = questionList(courseCode, courseProperty,
                                    QuesStructType.BOOL_ANSWER_QUESTION, parentProperty, sonProperty);

                            List<Question> fillList = null;
                            // fillList = questionList(courseCode,
                            // courseProperty,
                            // QuesStructType.FILL_BLANK_QUESTION,
                            // parentProperty, sonProperty);
                            List<Question> textList = null;
                            // textList = questionList(courseCode,
                            // courseProperty,
                            // QuesStructType.TEXT_ANSWER_QUESTION,
                            // parentProperty, sonProperty);

                            // 计算所有题型数量
                            Map<Long, Long> map = countQuesType(sinList, mulList, bolList, fillList, textList);
                            QuestionDistributeDto questionDistributeDto = new QuestionDistributeDto(
                                    courseProperty.getName(), parentProperty.getName(), sonProperty.getName(), map);
                            questionDistributes.add(questionDistributeDto);
                        }
                    } else {
                        // 一级属性不为空，二级属性为空
                        // 单选题集合
                        List<Question> sinList = questionList(courseCode, courseProperty,
                                QuesStructType.SINGLE_ANSWER_QUESTION, parentProperty, null);
                        // 多选题集合
                        List<Question> mulList = questionList(courseCode, courseProperty,
                                QuesStructType.MULTIPLE_ANSWER_QUESTION, parentProperty, null);
                        // 判断题集合
                        List<Question> bolList = questionList(courseCode, courseProperty,
                                QuesStructType.BOOL_ANSWER_QUESTION, parentProperty, null);

                        List<Question> fillList = null;
                        // fillList = questionList(courseCode, courseProperty,
                        // QuesStructType.FILL_BLANK_QUESTION, parentProperty,
                        // null);
                        List<Question> textList = null;
                        // textList = questionList(courseCode, courseProperty,
                        // QuesStructType.TEXT_ANSWER_QUESTION, parentProperty,
                        // null);

                        // 计算所有题型数量
                        Map<Long, Long> map = countQuesType(sinList, mulList, bolList, fillList, textList);
                        QuestionDistributeDto questionDistributeDto = new QuestionDistributeDto(
                                courseProperty.getName(), parentProperty.getName(), null, map);
                        questionDistributes.add(questionDistributeDto);
                    }
                }
            } else {
                // 一级属性为空
                QuestionDistributeDto questionDistributeDto = new QuestionDistributeDto(courseProperty.getName(), null,
                        null, null);
                questionDistributes.add(questionDistributeDto);
            }
        }

        return questionDistributes;
    }

    @SuppressWarnings("resource")
    private File writeExcel(List<QuestionDistributeDto> questionDistributes, String filePath) throws IOException {
        // 读取Excel模板
        InputStream in = this.getClass().getResourceAsStream("/quesDistinct.xlsx");
        // InputStream in =
        // this.getClass().getResourceAsStream("/quesDistinctAll.xlsx");

        // 获取第一个工作页
        Workbook workBook = new XSSFWorkbook(in);
        Sheet sheet = workBook.getSheetAt(0);

        // 往Excel中写入数据，从第5行开始
        for (int i = 0; i < questionDistributes.size(); i++) {
            // 创建一行：从第五行开始，跳过表头
            Row row = sheet.createRow(i + 4);

            // 获取这行的记录
            QuestionDistributeDto questionDistributeDto = questionDistributes.get(i);

            // 每列赋值
            row.createCell(0).setCellValue(questionDistributeDto.getCoursePropertyName());
            row.createCell(1).setCellValue(questionDistributeDto.getFirstPropertyName());
            row.createCell(2).setCellValue(questionDistributeDto.getSecondPropertyName());
            Map<Long, Long> map = questionDistributeDto.getMap();
            if (map == null) {
                for (int j = 0; j < 18; j++) {
                    row.createCell(j + 3).setCellValue(0);
                }
            } else {
                int j = 3;
                for (Long key : map.keySet()) {
                    row.createCell(j).setCellValue(map.get(key));
                    j++;
                }
            }
        }

        LOG.info("[WriteExcel] " + filePath);

        File file = new File(filePath);
        OutputStream out = new FileOutputStream(file);
        workBook.write(out);
        out.close();
        return file;
    }

    private Map<Long, Long> countQuesType(List<Question> sinList, List<Question> mulList, List<Question> bolList,
            List<Question> fillList, List<Question> textList) {
        Map<Long, Long> map = new TreeMap<>();
        map = buildMap(sinList, map, 1);
        map = buildMap(mulList, map, 2);
        map = buildMap(bolList, map, 3);

        if (fillList != null) {
            map = buildMap(fillList, map, 4);
        }
        if (textList != null) {
            map = buildMap(textList, map, 5);
        }

        // 给map的键排序
        Map<Long, Long> resultMap = sortMapByKey(map);
        return resultMap;
    }

    private Map<Long, Long> sortMapByKey(Map<Long, Long> map) {
        if (map == null || map.isEmpty()) {
            return null;
        }
        Map<Long, Long> sortMap = new TreeMap<Long, Long>(new Comparator<Long>() {

            public int compare(Long l1, Long l2) {
                return l1.compareTo(l2);
            }
        });
        sortMap.putAll(map);
        return sortMap;
    }

    private Map<Long, Long> buildMap(List<Question> quesList, Map<Long, Long> map, int questionType) {
        // 初始化map
        for (int i = 1; i < 7; i++) {
            if (i < 4) {
                map.put((long) (questionType * 100 + i), 0L);
            } else {
                map.put((long) (questionType * 100 + 10 + i - 3), 0L);
            }
        }
        for (Question question : quesList) {
            if (question.getPublicity()) {
                // 公开
                if (question.getDifficulty() != null && question.getDifficulty().equals("难")
                        || question.getDifficultyDegree() < 0.4 && question.getDifficultyDegree() > 0) {
                    map = buildMapSum(questionType * 100L + 1L, map);
                } else if (question.getDifficulty() != null && question.getDifficulty().equals("中")
                        || question.getDifficultyDegree() < 0.8 && question.getDifficultyDegree() > 0.3) {
                    map = buildMapSum(questionType * 100L + 2L, map);
                } else {
                    map = buildMapSum(questionType * 100L + 3L, map);
                }
            } else {
                // 非公开
                if (question.getDifficulty() != null && question.getDifficulty().equals("难")
                        || question.getDifficultyDegree() < 0.4 && question.getDifficultyDegree() > 0) {
                    map = buildMapSum(questionType * 100L + 11L, map);
                } else if (question.getDifficulty() != null && question.getDifficulty().equals("中")
                        || question.getDifficultyDegree() < 0.8 && question.getDifficultyDegree() > 0.3) {
                    map = buildMapSum(questionType * 100L + 12L, map);
                } else {
                    map = buildMapSum(questionType * 100L + 13L, map);
                }
            }
        }
        return map;
    }

    private Map<Long, Long> buildMapSum(long key, Map<Long, Long> map) {
        Long sum = map.get(key);
        map.put(key, sum + 1);
        return map;
    }

    public List<Question> questionList(String courseNo, CourseProperty courseProperty, QuesStructType quesStructType,
            Property parentProperty, Property sonProperty) {
        Query query = new Query();
        query.addCriteria(Criteria.where("orgId").is(courseProperty.getOrgId().toString()));
        query.addCriteria(Criteria.where("course.enable").is("true"));
        query.addCriteria(Criteria.where("course.code").is(courseNo));
        query.addCriteria(Criteria.where("questionType").is(quesStructType.name()));
        query.addCriteria(Criteria.where("quesProperties.coursePropertyName").is(courseProperty.getName()));
        // 二级属性不为空，那么一级属性也不为空
        if (sonProperty != null && sonProperty.getId() != null) {
            query.addCriteria(Criteria.where("quesProperties").elemMatch(Criteria.where("firstProperty.id")
                    .is(parentProperty.getId()).and("secondProperty.id").is(sonProperty.getId())));
        } else {
            if (parentProperty != null && parentProperty.getId() != null) {
                query.addCriteria(Criteria.where("quesProperties")
                        .elemMatch(Criteria.where("firstProperty.id").is(parentProperty.getId())));
            }
        }
        List<Question> questionList = this.mongoTemplate.find(query, Question.class);
        return questionList;
    }

    public List<Question> questionList2(String courseNo, CourseProperty courseProperty, QuesStructType quesStructType,
            Property parentProperty, Property sonProperty, List<Question> questions) {
        List<Question> questionList = new ArrayList<>();
        String id = courseNo + quesStructType.name() + courseProperty.getName();
        // 二级属性不为空，那么一级属性也不为空
        if (sonProperty != null && sonProperty.getId() != null) {
            id = id + parentProperty.getId() + sonProperty.getId();
        } else {
            if (parentProperty != null && parentProperty.getId() != null) {
                id = id + parentProperty.getId();
            }
        }
        for (Question question : questions) {
            List<String> idStrings = new ArrayList<>();
            String id_Q = question.getCourseNo() + question.getQuestionType();
            List<QuesProperty> quesProperties = question.getQuesProperties();
            if (quesProperties != null && quesProperties.size() > 0) {
                for (QuesProperty property : quesProperties) {
                    String idP = id_Q + property.getCoursePropertyName() + property.getFirstProperty().getId();
                    if (property.getSecondProperty() != null) {
                        idP = id_Q + property.getCoursePropertyName() + property.getFirstProperty().getId()
                                + property.getSecondProperty().getId();
                    }
                    idStrings.add(idP);
                }
                if (idStrings.contains(id)) {
                    questionList.add(question);
                }
            }
        }
        return questionList;
    }

    @Override
    public void downOriginalPaper(String paperId, String loginName, HttpServletResponse response) throws Exception {
//        String zipFileName = loginName + System.currentTimeMillis() + "";
//        try {
//            // 生成导出的试卷对象
//            PaperExp paperExp = paperService.getDownPaperExp(paperId);
//            File directory = new File(TEMP_FILE_EXP + File.separator + zipFileName);
//            if (!directory.exists()) {
//                directory.mkdirs();
//            }
//            String paperfileName = paperExp.getName() + "_" + paperExp.getCourseNo() + "_"
//                    + ExamFileType.PAPER.getName() + DOCX_SUFFIX;
//            File file = new File(TEMP_FILE_EXP + File.separator + zipFileName + File.separator + paperfileName);
//            List<WordprocessingMLPackage> wordPackages = getPkgList(paperId);
//            DocxProcessUtil.exportWordNew(paperExp, file, ExportPaperAbstractService.ORIGINAL_PAPER);
//            DocxProcessUtil.processImage(zipFileName + File.separator + paperfileName, wordPackages);
//            FileDisposeUtil.fileToZip(TEMP_FILE_EXP + File.separator + zipFileName, TEMP_FILE_EXP, zipFileName);
//            FileDisposeUtil.downloadFile(paperExp.getName() + "_" + paperExp.getCourse().getCode() + ".zip",
//                    TEMP_FILE_EXP + File.separator + zipFileName + ".zip", response);
//        } finally {
//            deteleFolder(TEMP_FILE_EXP, zipFileName);
//        }
    }

    /**
     * 获取当前试卷下所有试题WordPkg
     *
     * @param id
     * @return
     */
//    protected List<WordprocessingMLPackage> getPkgList(String id) {
//        Paper paper = Model.of(paperRepo.findById(id));
//        List<WordprocessingMLPackage> wordMLPackages = paperDetailUnitRepo.findByPaperOrderByNumber(paper).stream()
//                .map(PaperDetailUnit::getQuestion).collect(Collectors.toList()).stream()
//                .map(question -> getPkgObj(question)).collect(Collectors.toList());
//        return wordMLPackages;
//    }
//
//    private WordprocessingMLPackage getPkgObj(Question question) {
//        String pkgPathId = question.getQuesPkgPathId();
//        QuestionPkgPath quesPkg = quesPkgPathRepo.findFirstById(pkgPathId);
//        if (quesPkg == null) {
//            byte[] bytes = new byte[0];
//            return DocxProcessUtil.getPkg(bytes);
//        }
//        byte[] pkgByte = quesPkg.getQuesPkg();
//        return DocxProcessUtil.getPkg(pkgByte);
//    }

    @Override
    public void downQuestionDistributeByPapers(String paperIds, HttpServletResponse response) throws IOException {
        List<QuestionDistributeDto> questionDistributes = new ArrayList<>();

        // 定义课程集合
        List<String> courseCodes = new ArrayList<>();

        // 定义试题集合
        List<Question> questions = new ArrayList<>();

        // 查询试卷集合
        String[] paperIdArray = paperIds.split(",");
        for (int i = 0; i < paperIdArray.length; i++) {
            Paper basePaper = Model.of(paperRepo.findById(paperIdArray[i]));
            courseCodes.add(basePaper.getCourse().getCode());
            // 将小题全部取出来,只取一次,减少对数据库的查询
            List<PaperDetailUnit> allPaperDetailUnits = paperDetailUnitRepo.findByPaper(basePaper);
            for (PaperDetailUnit unit : allPaperDetailUnits) {
                if (unit.getQuestionType().equals(QuesStructType.SINGLE_ANSWER_QUESTION)
                        || unit.getQuestionType().equals(QuesStructType.MULTIPLE_ANSWER_QUESTION)
                        || unit.getQuestionType().equals(QuesStructType.BOOL_ANSWER_QUESTION)) {
                    questions.add(unit.getQuestion());
                }
            }
        }

        // 根据课程code查询课程属性集合
        for (String courseCode : courseCodes) {
            List<CourseProperty> courseProperties = coursePropertyRepo.findByCourseCodeAndEnable(courseCode, true);
            // 遍历课程属性集合，根据课程属性查询一级
            if (courseProperties != null && courseProperties.size() > 0) {
                for (CourseProperty courseProperty : courseProperties) {
                    List<Property> parentProperties = propertyService.findParentProperties(courseProperty.getId(),
                            courseProperty.getOrgId());
                    if (parentProperties != null && parentProperties.size() > 0) {
                        for (Property parentProperty : parentProperties) {
                            List<Property> sonProperties = propertyService.findSonProperties(parentProperty.getId());
                            if (sonProperties != null && sonProperties.size() > 0) {
                                for (Property sonProperty : sonProperties) {
                                    // 单选题集合
                                    List<Question> sinList = questionList2(courseCode, courseProperty,
                                            QuesStructType.SINGLE_ANSWER_QUESTION, parentProperty, sonProperty,
                                            questions);
                                    // 多选题集合
                                    List<Question> mulList = questionList2(courseCode, courseProperty,
                                            QuesStructType.MULTIPLE_ANSWER_QUESTION, parentProperty, sonProperty,
                                            questions);
                                    // 判断题集合
                                    List<Question> bolList = questionList2(courseCode, courseProperty,
                                            QuesStructType.BOOL_ANSWER_QUESTION, parentProperty, sonProperty,
                                            questions);

                                    List<Question> fillList = null;
                                    // fillList = questionList2(courseNo,
                                    // courseProperty,
                                    // QuesStructType.FILL_BLANK_QUESTION,
                                    // parentProperty, sonProperty, questions);
                                    List<Question> textList = null;
                                    // textList = questionList2(courseNo,
                                    // courseProperty,
                                    // QuesStructType.TEXT_ANSWER_QUESTION,
                                    // parentProperty, sonProperty, questions);

                                    // 计算所有题型数量
                                    Map<Long, Long> map = countQuesType(sinList, mulList, bolList, fillList, textList);
                                    QuestionDistributeDto questionDistributeDto = new QuestionDistributeDto(
                                            courseProperty.getName(), parentProperty.getName(), sonProperty.getName(),
                                            map);
                                    questionDistributes.add(questionDistributeDto);
                                }
                            } else {
                                // 一级属性不为空，二级属性为空
                                // 单选题集合
                                List<Question> sinList = questionList2(courseCode, courseProperty,
                                        QuesStructType.SINGLE_ANSWER_QUESTION, parentProperty, null, questions);
                                // 多选题集合
                                List<Question> mulList = questionList2(courseCode, courseProperty,
                                        QuesStructType.MULTIPLE_ANSWER_QUESTION, parentProperty, null, questions);
                                // 判断题集合
                                List<Question> bolList = questionList2(courseCode, courseProperty,
                                        QuesStructType.BOOL_ANSWER_QUESTION, parentProperty, null, questions);

                                List<Question> fillList = null;
                                // fillList = questionList2(courseNo,
                                // courseProperty,
                                // QuesStructType.FILL_BLANK_QUESTION,
                                // parentProperty, null, questions);
                                List<Question> textList = null;
                                // textList = questionList2(courseNo,
                                // courseProperty,
                                // QuesStructType.TEXT_ANSWER_QUESTION,
                                // parentProperty, null, questions);

                                // 计算所有题型数量
                                Map<Long, Long> map = countQuesType(sinList, mulList, bolList, fillList, textList);
                                QuestionDistributeDto questionDistributeDto = new QuestionDistributeDto(
                                        courseProperty.getName(), parentProperty.getName(), null, map);
                                questionDistributes.add(questionDistributeDto);
                            }
                        }
                    } else {
                        // 一级属性为空
                        QuestionDistributeDto questionDistributeDto = new QuestionDistributeDto(
                                courseProperty.getName(), null, null, null);
                        questionDistributes.add(questionDistributeDto);
                    }
                }
            }

            final String fileName = System.currentTimeMillis() + "试题分布.xlsx";
            final String filePath = TEMP_FILE_EXP + File.separator + fileName;

            // 生成Excel导出
            File tempFile = this.writeExcel(questionDistributes, filePath);
            FileDisposeUtil.downloadFile(fileName, filePath, response);
            FileUtils.deleteQuietly(tempFile);
        }
    }

    @Override
    public void downOriginalPaperPlus(String paperId, Long rootOrgId, HttpServletResponse response) throws IOException{
        String zipFileName = IdUtils.uuid();
        File directory = new File(TEMP_FILE_EXP + File.separator + zipFileName);
        if (!directory.exists()) {
            directory.mkdirs();
        }
        // doc固定源文件目录
//        File docxDir = new File(JsonExportUtil.getDocxBasePath());
//        // 将要生成的doc源文件目录
//        File docxTargetDir = new File(directory.getAbsolutePath() + "/docx/");
//        docxTargetDir.mkdir();
        try {
            // 复制docx基础文件
//            FileUtils.copyDirectory(docxDir, docxTargetDir);
            // 生成导出的试卷对象
            PaperExp paperExp = paperService.getDownPaperExp(paperId);
            
            PaperUtil.setQuestionSeq(paperExp.getPaperDetails(), PaperSeqMode.MODE4);
//            // 处理并生成doc源文件
//            dispose(docxTargetDir, paperExp);
//            // 压缩docx源文件
//            String paperfileName = paperExp.getName() + "_" + paperExp.getCourseNo() + "_"
//                    + ExamFileType.PAPER.getName();
//            File zipfile = new File(docxTargetDir.getParentFile().getAbsolutePath() + File.separator + "data"
//                    + File.separator + paperfileName + ZIP_SUFFIX);
//            zipfile.getParentFile().mkdir();
//            File docfile = new File(docxTargetDir.getParentFile().getAbsolutePath() + File.separator + "data"
//                    + File.separator + File.separator + paperfileName + DOCX_SUFFIX);
//            FileDisposeUtil.createZip(docxTargetDir.getAbsolutePath(), zipfile.getAbsolutePath());
//            // 修改压缩包为doc文件
//            zipfile.renameTo(docfile);
            File docfile= ExportPaperUtil.createOriginPaperDocFile(paperExp, directory);
            // doc文件加入下载包中
            FileDisposeUtil.fileToZip(docfile.getParentFile().getAbsolutePath(),
                    directory.getAbsolutePath(), zipFileName);
            // 下载文件
            FileDisposeUtil.downloadFile(paperExp.getName() + "_" + paperExp.getCourse().getCode() + ".zip",
                    directory.getAbsolutePath() + File.separator + zipFileName + ".zip", response);
        } finally {
            FileUtils.deleteDirectory(directory);
        }

    }

//    private void dispose(File docxTargetDir, PaperExp paperExp) throws IOException {
//        ExportTempDataDto dto = new ExportTempDataDto();
//        if (paperExp.getPaperDetails() != null && paperExp.getPaperDetails().size() > 0) {
//            for (PaperDetailExp pde : paperExp.getPaperDetails()) {
//                dto.setMainNum(dto.getMainNum() + 1);
//                dto.setSubNum(0);
//                if (pde.getPaperDetailUnits() != null && pde.getPaperDetailUnits().size() > 0) {
//                    for (PaperDetailUnitExp pdue : pde.getPaperDetailUnits()) {
//                        Question qes = pdue.getQuestion();
//                        disposeQuestion(qes, dto);
//                    }
//                }
//            }
//        }
//        // content-type
//        writeContentType(docxTargetDir, dto);
//        // document
//        writeDocument(docxTargetDir, paperExp);
//        // document-rel
//        writeDocumentRel(docxTargetDir, dto);
//        // image file
//        writeImage(docxTargetDir, dto);
//    }
//
//    private void writeImage(File docxTargetDir, ExportTempDataDto dto) throws IOException {
//        for (SectionElement se : dto.getImages()) {
//            File file = new File(docxTargetDir.getAbsolutePath() + "/word/media/image" + se.getParams().getIndex() + "."
//                    + se.getParams().getType());
//            String base64 = se.getValue();
//            if (base64.contains("data:image")) {
//                base64 = base64.substring(base64.indexOf(",") + 1);
//            }
//            BASE64Decoder decoder = new BASE64Decoder();
//            byte[] bytes = decoder.decodeBuffer(base64);
//            FileUtils.writeByteArrayToFile(file, bytes);
//        }
//    }
//
//    private void writeDocumentRel(File docxTargetDir, ExportTempDataDto dto) throws IOException {
//        Map<String, Object> map = new HashMap<String, Object>();
//        map.put("images", dto.getImages());
//        String doc = JsonExportUtil.getDocumentRelDoc(map);
//        File file = new File(docxTargetDir.getAbsolutePath() + "/word/_rels/document.xml.rels");
//        FileUtils.writeStringToFile(file, doc, "utf-8");
//    }
//
//    private void writeContentType(File docxTargetDir, ExportTempDataDto dto) throws IOException {
//        Map<String, Object> map = new HashMap<String, Object>();
//        map.put("images", dto.getTypes());
//        String doc = JsonExportUtil.getContentTypesDoc(map);
//        File file = new File(docxTargetDir.getAbsolutePath() + "/[Content_Types].xml");
//        FileUtils.writeStringToFile(file, doc, "utf-8");
//    }
//
//    private void writeDocument(File docxTargetDir, PaperExp paperExp) throws IOException {
//        String doc = JsonExportUtil.getDocumentDoc(paperExp);
//        File file = new File(docxTargetDir.getAbsolutePath() + "/word/document.xml");
//        FileUtils.writeStringToFile(file, doc, "utf-8");
//    }
//
//    private void disposeQuestion(Question qes, ExportTempDataDto dto) {
//        if (qes != null) {
//            List<JSection> slist1 = JsonExportUtil.getSections(qes.getQuesBody());
//            if (slist1 != null && slist1.size() > 0) {
//                if (qes.getSubQuestions() == null || qes.getSubQuestions().size() == 0) {// 套题题干不加题号
//                    dto.setSubNum(dto.getSubNum() + 1);
//                    SectionElement se = new SectionElement();
//                    se.setType(JsonExportUtil.ELEMENT_TYPE_TEXT);
//                    se.setValue(dto.getSubNum() + ".");
//                    slist1.get(0).getElements().add(0, se);
//                }
//
//                htmlToDoc(slist1, dto);
//                qes.setQuesBodyWord(getQuestionDoc(slist1));
//            }
//
//            if (qes.getQuesOptions() != null && qes.getQuesOptions().size() > 0) {
//                int index = 0;
//                for (QuesOption qo : qes.getQuesOptions()) {
//                    List<JSection> slist2 = JsonExportUtil.getSections(qo.getOptionBody());
//                    if (slist2 != null && slist2.size() > 0) {
//                        SectionElement se = new SectionElement();
//                        se.setType(JsonExportUtil.ELEMENT_TYPE_TEXT);
//                        se.setValue(JsonExportUtil.QUESOPS.charAt(index) + ".");
//                        index++;
//                        slist2.get(0).getElements().add(0, se);
//                        htmlToDoc(slist2, dto);
//                        qo.setOptionBodyWord(getQuestionDoc(slist2));
//                    }
//
//                }
//            }
//            List<JSection> slist3 = JsonExportUtil.getSections(qes.getQuesAnswer());
//            if (slist3 != null && slist3.size() > 0) {
//                SectionElement se = new SectionElement();
//                se.setType(JsonExportUtil.ELEMENT_TYPE_TEXT);
//                se.setValue("[答案]:");
//                slist3.get(0).getElements().add(0, se);
//
//                htmlToDoc(slist3, dto);
//                qes.setQuesAnswerWord(getQuestionDoc(slist3));
//            }
//
//            if (qes.getSubQuestions() != null && qes.getSubQuestions().size() > 0) {
//                dto.setSubNum(0);
//                for (Question sunqes : qes.getSubQuestions()) {
//                    disposeQuestion(sunqes, dto);// 递归处理套题
//                }
//            }
//        }
//    }
//
//    private void htmlToDoc(List<JSection> slist, ExportTempDataDto dto) {
//        for (JSection js : slist) {
//            for (SectionElement se : js.getElements()) {
//                if (JsonExportUtil.ELEMENT_TYPE_IMG.equals(se.getType())) {
//                    dto.setIndex(dto.getIndex() + 1);
//                    se.getParams().setIndex(dto.getIndex());
//                    se.getParams().setRid(JsonExportUtil.ELEMENT_TYPE_RID + dto.getIndex());
//                    se.getParams().setType(getImageType(se.getValue()));
//                    dto.getTypes().add(se.getParams().getType());
//                    dto.getImages().add(se);
//                }
//            }
//        }
//    }
//
//    private String getImageType(String base64) {
//        return base64.substring(11, base64.indexOf(";"));
//    }
//
//    private String getQuestionDoc(List<JSection> sections) {
//        Map<String, Object> map = new HashMap<String, Object>();
//        map.put("sections", sections);
//        String doc = JsonExportUtil.getQuestionSectionDoc(map);
//        return doc;
//    }
}