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

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Example;
import org.springframework.stereotype.Service;

import cn.com.qmth.examcloud.api.commons.enums.CallType;
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.Model;
import cn.com.qmth.examcloud.core.questions.base.question.enums.QuesStructType;
import cn.com.qmth.examcloud.core.questions.dao.AudioTimeConfigRepo;
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.AudioTimeConfig;
import cn.com.qmth.examcloud.core.questions.dao.entity.ExamPaper;
import cn.com.qmth.examcloud.core.questions.dao.entity.ExtractConfig;
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.dao.entity.QuestionAudio;
import cn.com.qmth.examcloud.core.questions.service.ExtractConfigProviderService;
import cn.com.qmth.examcloud.core.questions.service.ExtractConfigService;
import cn.com.qmth.examcloud.core.questions.service.PaperService;
import cn.com.qmth.examcloud.core.questions.service.QuesService;
import cn.com.qmth.examcloud.core.questions.service.QuestionAudioService;
import cn.com.qmth.examcloud.core.questions.service.bean.QuestionAnswerConvert;
import cn.com.qmth.examcloud.core.questions.service.bean.extract.ExtractConfigPaper;
import cn.com.qmth.examcloud.question.commons.core.paper.DefaultPaper;
import cn.com.qmth.examcloud.question.commons.core.paper.DefaultQuestionGroup;
import cn.com.qmth.examcloud.question.commons.core.paper.DefaultQuestionStructureWrapper;
import cn.com.qmth.examcloud.question.commons.core.paper.DefaultQuestionUnitWrapper;
import cn.com.qmth.examcloud.question.commons.core.question.DefaultQuestion;
import cn.com.qmth.examcloud.question.commons.core.question.DefaultQuestionOption;
import cn.com.qmth.examcloud.question.commons.core.question.DefaultQuestionStructure;
import cn.com.qmth.examcloud.question.commons.core.question.DefaultQuestionUnit;
import cn.com.qmth.examcloud.question.commons.core.question.QuestionType;
import cn.com.qmth.examcloud.support.cache.CacheHelper;
import cn.com.qmth.examcloud.support.cache.bean.ExtractConfigCacheBean;
import cn.com.qmth.examcloud.support.cache.bean.ExtractConfigDetailCacheBean;
import cn.com.qmth.examcloud.support.cache.bean.ExtractConfigPaperCacheBean;
import cn.com.qmth.examcloud.support.filestorage.FileStorageUtil;

/**
 * @author weiwenhai
 * @date 2018.8.15
 * @company qmth
 * @describle provider中的service方法
 * @code 020
 */
@Service("extractConfigCloudService")
public class ExtractConfigProviderServiceImpl implements ExtractConfigProviderService {

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

	@Autowired
	private ExtractConfigService extractConfigService;

	@Autowired
	private PaperRepo paperRepo;

	@Autowired
	private PaperDetailRepo paperDetailRepo;

	@Autowired
	private PaperDetailUnitRepo paperDetailUnitRepo;

	@Autowired
	private QuesRepo quesRepo;

	@Autowired
	private AudioTimeConfigRepo audioTimeConfigRepo;

	@Autowired
	private QuestionAudioService questionAudioService;

	@Autowired
	private QuesService quesService;

	@Autowired
	private PaperService paperService;

	// @Autowired
	// private SysProperty sysProperty;

	@Override
	public ExtractConfigCacheBean getExtractConfig(Long examId, String courseCode) {
		ExtractConfig extractConfig = extractConfigService.findConfig(new ExtractConfig(examId, courseCode));
		if (extractConfig == null) {
			throw new StatusException("500", "该课程调卷规则未制定，请联系学校！");
		}
		if (CallType.WHOLE_SET.equals(extractConfig.getCallType())) {
			if (CollectionUtils.isEmpty(extractConfig.getExamPaperList())) {
				throw new StatusException("500", "可供抽取的试卷集合为空！");
			}
		}

		ExtractConfigCacheBean cacheBean = new ExtractConfigCacheBean();
		cacheBean.setId(extractConfig.getId());
		cacheBean.setExamId(examId);
		cacheBean.setCallType(extractConfig.getCallType());
		cacheBean.setCourseCode(courseCode);
		cacheBean.setRandomPaperId(extractConfig.getRandomPaperId());
		cacheBean.setPlayTime(extractConfig.getPlayTime());
		cacheBean.setSortQuestionOrder(getByShort(extractConfig.getScrambling_the_question_order()));
		cacheBean.setSortOptionOrder(getByShort(extractConfig.getScrambling_the_option_order()));

		if (CallType.WHOLE_SET.equals(extractConfig.getCallType())) {
			List<ExtractConfigDetailCacheBean> details = new ArrayList<>();
			for (ExamPaper examPaper : extractConfig.getExamPaperList()) {
				details.add(new ExtractConfigDetailCacheBean(examPaper.getGroupCode(), examPaper.getPaper().getId(),
						examPaper.getWeight()));
			}
			cacheBean.setDetails(details);
		}

		return cacheBean;
	}
	
	private boolean getByShort(Short s) {
		if(s==null) {
			return false;
		}else {
			return s!=0;
		}
	}

	@Override
	public ExtractConfigPaperCacheBean getExtractConfigPaper(Long examId, String courseCode, String groupCode,
			String paperId) {
		DefaultPaper defaultPaper = this.buildDefaultByBasePaper(paperId, examId, courseCode, groupCode);

		ExtractConfigPaperCacheBean cacheBean = new ExtractConfigPaperCacheBean();
		cacheBean.setDefaultPaper(defaultPaper);
		return cacheBean;
	}

	@Override
	public ExtractConfigPaper getDefaultPaper(Long examId, String courseCode, String groupCode) {
		LOG.info("调卷开始...");

		ExtractConfigCacheBean extractConfigCache = CacheHelper.getExtractConfig(examId, courseCode);
		if (extractConfigCache == null) {
			throw new StatusException("500", "该课程调卷规则未制定，请联系学校！");
		}

		final String msg = "该考试和课程下调卷规则中试卷不存在,请重新制定调卷规则！";
		Map<String, String> paperTypeMaps = this.getExamPaperByProbability(extractConfigCache.getDetails());
		if (paperTypeMaps.isEmpty()) {
			throw new StatusException("500", msg);
		}

		String basePaperId = paperTypeMaps.get(groupCode);
		if (StringUtils.isEmpty(basePaperId)) {
			throw new StatusException("500", msg);
		}

		LOG.info("构建试卷结构..." + basePaperId);
		ExtractConfigPaperCacheBean extractConfigPaperCache = CacheHelper.getExtractConfigPaper(examId, courseCode,
				groupCode, basePaperId);
		if (extractConfigPaperCache == null) {
			throw new StatusException("500", msg);
		}

		ExtractConfigPaper result = new ExtractConfigPaper();
		result.setDefaultPaper(extractConfigPaperCache.getDefaultPaper());
		result.setPaperId(basePaperId);
		result.setSortQuestionOrder(extractConfigCache.getSortQuestionOrder());
		result.setSortOptionOrder(extractConfigCache.getSortOptionOrder());
		return result;
	}

	/**
	 * 每个试卷类型取出一套试卷 {A:paperId,B:paperId} A是试卷类型，paperId是A类型下选定的试卷ID
	 */
	private Map<String, String> getExamPaperByProbability(List<ExtractConfigDetailCacheBean> examPapers) {
		if (CollectionUtils.isEmpty(examPapers)) {
			throw new StatusException("500", "可供抽取的试卷集合为空！");
		}

		Map<String, List<ExtractConfigDetailCacheBean>> examPaperMaps = new HashMap<>();
		for (ExtractConfigDetailCacheBean examPaper : examPapers) {
			if (examPaperMaps.containsKey(examPaper.getGroupCode())) {
				examPaperMaps.get(examPaper.getGroupCode()).add(examPaper);
			} else {
				List<ExtractConfigDetailCacheBean> list = new ArrayList<>();
				list.add(examPaper);
				examPaperMaps.put(examPaper.getGroupCode(), list);
			}
		}

		Map<String, String> paperTypeMaps = new HashMap<>();
		for (Map.Entry<String, List<ExtractConfigDetailCacheBean>> entry : examPaperMaps.entrySet()) {
			List<ExtractConfigDetailCacheBean> list = examPaperMaps.get(entry.getKey());

			String paperId = this.getPaperByProbability(list);
			if (StringUtils.isEmpty(paperId)) {
				continue;
			}

			paperTypeMaps.put(entry.getKey(), paperId);
		}

		return paperTypeMaps;
	}

	/**
	 * 根据设定几率取出一套试卷
	 */
	private String getPaperByProbability(List<ExtractConfigDetailCacheBean> examPapers) {
		int sum = 0;
		for (ExtractConfigDetailCacheBean examPaper : examPapers) {
			sum += examPaper.getWeight();
		}

		// 从1开始
		int r = new Random().nextInt(sum) + 1;
		for (ExtractConfigDetailCacheBean examPaper : examPapers) {
			r -= examPaper.getWeight();
			if (r <= 0) {
				return examPaper.getPaperId();// 选中
			}
		}

		return null;
	}

	/**
	 * 根据paper对象构建DefaultPaper对象
	 */
	public DefaultPaper buildDefaultByBasePaper(String basePaperId, Long examId, String courseCode, String groupCode) {
		Paper basePaper = Model.of(paperRepo.findById(basePaperId));
		return this.buildDefaultByBasePaper(basePaper, examId, courseCode, groupCode);
	}

	/**
	 * 根据paper对象构建DefaultPaper对象
	 */
	public DefaultPaper buildDefaultByBasePaper(Paper basePaper, Long examId, String courseCode, String groupCode) {
		LOG.debug("开始包装网考需要的试卷结构...");

		// 获取大题
		List<PaperDetail> paperDetails = paperDetailRepo.findByPaper(basePaper);

		// 排序大题
		Collections.sort(paperDetails);

		// 将小题全部取出来,只取一次,减少对数据库的查询
		List<PaperDetailUnit> allPaperDetailUnits = paperDetailUnitRepo.findByPaper(basePaper);
		boolean fullyObjective = checkIsAllQbjectiveQuestion(allPaperDetailUnits);

		// 根据大题id将小题归类
		Map<String, List<PaperDetailUnit>> pduMap = allPaperDetailUnits.stream()
				.collect(Collectors.groupingBy(PaperDetailUnit::getDetailId));

		LOG.debug("循环大题，开始组装对象...");

		// 生成新的分组集合
		List<DefaultQuestionGroup> questionGroupList = new ArrayList<>();
		for (int i = 0; i < paperDetails.size(); i++) {
			PaperDetail paperDetail = paperDetails.get(i);
			DefaultQuestionGroup defaultQuestionGroup = new DefaultQuestionGroup();
			defaultQuestionGroup.setGroupName(paperDetail.getName());
			defaultQuestionGroup.setGroupScore(paperDetail.getScore());

			// 获取原小题的集合
			List<PaperDetailUnit> paperDetailUnits = pduMap.get(paperDetail.getId());
			if (CollectionUtils.isEmpty(paperDetailUnits)) {
				LOG.warn("试卷大题下面没有小题！");
				throw new StatusException("500", "考试试卷有误，请联系老师！");
			}

			// 按题号顺序排序
			Collections.sort(paperDetailUnits);

			// 生成新的题包装器集合
			List<DefaultQuestionStructureWrapper> questionWrapperList = new ArrayList<>();
			for (int j = 0; j < paperDetailUnits.size(); j++) {
				PaperDetailUnit paperDetailUnit = paperDetailUnits.get(j);
				DefaultQuestionStructureWrapper defaultQuestionStructureWrapper = new DefaultQuestionStructureWrapper();
				defaultQuestionStructureWrapper.setQuestionId(paperDetailUnit.getQuestion().getId());
				defaultQuestionStructureWrapper.setVersion(CommonUtils.QUESTION_VERSION);
				defaultQuestionStructureWrapper.setQuestionScore(paperDetailUnit.getScore());
				defaultQuestionStructureWrapper.setTimeLimit(paperDetailUnit.getTimeLimit());

				if (examId != null) {
					// 设置音频播放次数
					if (paperDetailUnit.getQuestion().getHasAudio() != null
							&& paperDetailUnit.getQuestion().getHasAudio()) {
						AudioTimeConfig find = new AudioTimeConfig(examId.toString(), courseCode, groupCode,
								paperDetailUnit.getQuestion().getId());
						AudioTimeConfig audioTimeConfig = Model.of(audioTimeConfigRepo.findOne(Example.of(find)));
						if (audioTimeConfig != null) {
							defaultQuestionStructureWrapper.setLimitedPlayTimes(audioTimeConfig.getPlayTime());
						}
					}
				}

				// 生成新的题单元包装器
				List<DefaultQuestionUnitWrapper> defaultQuestionUnitWrappers = new ArrayList<>();
				if (paperDetailUnit.getQuestion().getQuestionType() == QuesStructType.NESTED_ANSWER_QUESTION) {
					List<Question> subQuesList = paperDetailUnit.getQuestion().getSubQuestions();
					List<Double> scoreList = paperDetailUnit.getSubScoreList();
					if (subQuesList != null && subQuesList.size() > 0) {
						for (int k = 0; k < subQuesList.size(); k++) {
							DefaultQuestionUnitWrapper defaultQuestionUnitWrapper = buildQuesUnitWrapper(
									subQuesList.get(k), scoreList.get(k));
							defaultQuestionUnitWrappers.add(defaultQuestionUnitWrapper);
						}
					}
				} else {
					DefaultQuestionUnitWrapper defaultQuestionUnitWrapper = buildQuesUnitWrapper(
							paperDetailUnit.getQuestion(), paperDetailUnit.getScore());
					defaultQuestionUnitWrappers.add(defaultQuestionUnitWrapper);
				}

				defaultQuestionStructureWrapper.setQuestionUnitWrapperList(defaultQuestionUnitWrappers);
				questionWrapperList.add(defaultQuestionStructureWrapper);
			}

			defaultQuestionGroup.setQuestionWrapperList(questionWrapperList);
			questionGroupList.add(defaultQuestionGroup);
		}

		DefaultPaper defaultPaper = new DefaultPaper();
		defaultPaper.setName(basePaper.getName());
		defaultPaper.setQuestionGroupList(questionGroupList);
		defaultPaper.setFullyObjective(fullyObjective);

		return defaultPaper;
	}

	/**
	 * 根据question生成题单元包装器
	 *
	 * @param question
	 * @param score
	 * @return
	 */
	private DefaultQuestionUnitWrapper buildQuesUnitWrapper(Question question, Double score) {
		Integer[] optionPermutation = null;
		if (question.getQuestionType() == QuesStructType.SINGLE_ANSWER_QUESTION
				|| question.getQuestionType() == QuesStructType.MULTIPLE_ANSWER_QUESTION) {
			int length = question.getQuesOptions().size();
			optionPermutation = new Integer[length];

			for (int i = 0; i < length; i++) {
				optionPermutation[i] = i;
			}
		}

		DefaultQuestionUnitWrapper defaultQuestionUnitWrapper = new DefaultQuestionUnitWrapper();
		defaultQuestionUnitWrapper.setOptionPermutation(optionPermutation);
		defaultQuestionUnitWrapper.setQuestionScore(score);
		defaultQuestionUnitWrapper.setQuestionType(getByOldType(question.getQuestionType()));
		defaultQuestionUnitWrapper.setAnswerType(question.getAnswerType());// 作答类型
		return defaultQuestionUnitWrapper;
	}

	/**
	 * 题型转换方法
	 *
	 * @param quesStructType
	 * @return
	 */
	private QuestionType getByOldType(QuesStructType quesStructType) {
		if (quesStructType == QuesStructType.BOOL_ANSWER_QUESTION) {
			return QuestionType.TRUE_OR_FALSE;
		}
		if (quesStructType == QuesStructType.FILL_BLANK_QUESTION) {
			return QuestionType.FILL_UP;
		}
		if (quesStructType == QuesStructType.MULTIPLE_ANSWER_QUESTION) {
			return QuestionType.MULTIPLE_CHOICE;
		}
		if (quesStructType == QuesStructType.SINGLE_ANSWER_QUESTION) {
			return QuestionType.SINGLE_CHOICE;
		}
		if (quesStructType == QuesStructType.TEXT_ANSWER_QUESTION) {
			return QuestionType.ESSAY;
		}
		return null;
	}

	@Override
	public DefaultQuestion getDefaultQuestion(Long examId, String courseCode, String groupCode, String questionId) {
		Question question = Model.of(quesRepo.findById(questionId));
		if (question == null) {
			throw new StatusException("500", "试题不存在！");
		}
		quesService.formatQues(question);

		// 封装成新的题单元集合
		DefaultQuestionStructure defaultQuestionStructure = new DefaultQuestionStructure();
		if (question.getHasAudio() == null || false == question.getHasAudio()) {
			defaultQuestionStructure.setHasAudios(false);
		} else {
			defaultQuestionStructure.setHasAudios(true);
		}
		defaultQuestionStructure.setVersion(CommonUtils.QUESTION_VERSION);

		List<DefaultQuestionUnit> questionUnitList = new ArrayList<>();
		if (question.getQuestionType() == QuesStructType.NESTED_ANSWER_QUESTION) {
			defaultQuestionStructure.setBody(question.getQuesBody());

			// 获取套题下面所有子题
			List<Question> subQuesList = question.getSubQuestions();
			if (CollectionUtils.isNotEmpty(subQuesList)) {
				for (int i = 0; i < subQuesList.size(); i++) {
					Question subQuestion = subQuesList.get(i);
					DefaultQuestionUnit defaultQuestionUnit = buildQuestionUnit(subQuestion);
					questionUnitList.add(defaultQuestionUnit);
				}
			}
		} else {
			DefaultQuestionUnit defaultQuestionUnit = buildQuestionUnit(question);
			questionUnitList.add(defaultQuestionUnit);
		}

		defaultQuestionStructure.setQuestionUnitList(questionUnitList);
		DefaultQuestion defaultQuestion = new DefaultQuestion();
		defaultQuestion.setId(questionId);
		defaultQuestion.setMasterVersion(defaultQuestionStructure);

		if (examId != null) {
			appendAudioFlag(defaultQuestion, String.valueOf(examId), courseCode, groupCode, question);
		}

		// 获取试题信息带答案（敏感信息日志，用于排查调用者）
		LOG.warn("$$$getQuestionWithAnswer questionId:{} examId:{} courseCode:{} groupCode:{}", questionId, examId,
				courseCode, groupCode);
		return defaultQuestion;
	}

	/**
	 * 构建试题单元
	 *
	 * @param question
	 * @return
	 */
	private DefaultQuestionUnit buildQuestionUnit(Question question) {
		DefaultQuestionUnit defaultQuestionUnit = new DefaultQuestionUnit();
		defaultQuestionUnit.setAnswerType(question.getAnswerType());// 作答类型
		defaultQuestionUnit.setBody(question.getQuesBody());
		defaultQuestionUnit.setQuestionType(getByOldType(question.getQuestionType()));

		// 如果是单选或者多选，添加选项和答案转换
		if (question.getQuestionType() == QuesStructType.SINGLE_ANSWER_QUESTION
				|| question.getQuestionType() == QuesStructType.MULTIPLE_ANSWER_QUESTION) {
			List<DefaultQuestionOption> defaultQuestionOptions = new ArrayList<>();
			List<QuesOption> quesOptions = question.getQuesOptions();

			if (quesOptions != null && quesOptions.size() > 0) {
				for (int i = 0; i < quesOptions.size(); i++) {
					QuesOption quesOption = quesOptions.get(i);
					DefaultQuestionOption defaultQuestionOption = new DefaultQuestionOption();
					defaultQuestionOption.setBody(quesOption.getOptionBody());
					defaultQuestionOptions.add(defaultQuestionOption);
				}
			}
			defaultQuestionUnit.setQuestionOptionList(defaultQuestionOptions);
			defaultQuestionUnit.setRightAnswer(QuestionAnswerConvert.parseQuestionOptionAnswers(quesOptions));
		} else {
			defaultQuestionUnit.setRightAnswer(QuestionAnswerConvert.parseQuestionAnswers(question));
		}

		return defaultQuestionUnit;
	}

	/**
	 * html中添加音频标签
	 *
	 * @param defaultQuestion
	 * @param examId
	 * @param courseCode
	 * @param groupCode
	 * @param question
	 */
	private void appendAudioFlag(DefaultQuestion defaultQuestion, String examId, String courseCode, String groupCode,
			Question question) {
		if (question.getHasAudio() != null && question.getHasAudio() == true) {
			// 1.判断questionDto是否含有音频，如果有添加音频播放次数
			AudioTimeConfig audioTimeConfig = Model.of(audioTimeConfigRepo
					.findOne(Example.of(new AudioTimeConfig(examId, courseCode, groupCode, question.getId()))));
			if (audioTimeConfig != null) {
				// 2.1 取到题干，给a标签添加url
				String quesBody = null;
				if (StringUtils.isNotBlank(defaultQuestion.getMasterVersion().getBody())) {
					// 套题
					quesBody = defaultQuestion.getMasterVersion().getBody();
					defaultQuestion.getMasterVersion().setBody(buildBody(quesBody, audioTimeConfig.getPlayTime()));
				} else {
					DefaultQuestionUnit defaultQuestionUnit = (DefaultQuestionUnit) defaultQuestion.getMasterVersion()
							.getQuestionUnitList().get(0);
					quesBody = defaultQuestionUnit.getBody();
					defaultQuestionUnit.setBody(buildBody(quesBody, audioTimeConfig.getPlayTime()));
					if (defaultQuestionUnit.getQuestionType() == QuestionType.SINGLE_CHOICE
							|| defaultQuestionUnit.getQuestionType() == QuestionType.MULTIPLE_CHOICE) {
						List<DefaultQuestionOption> questionOptionList = defaultQuestionUnit.getQuestionOptionList();
						if (questionOptionList != null && questionOptionList.size() > 0) {
							for (int i = 0; i < questionOptionList.size(); i++) {
								DefaultQuestionOption defaultQuestionOption = questionOptionList.get(i);
								defaultQuestionOption.setBody(
										buildBody(defaultQuestionOption.getBody(), audioTimeConfig.getPlayTime()));
							}
						}
					}
				}
			} else {
				String quesBody = null;
				if (StringUtils.isNotBlank(defaultQuestion.getMasterVersion().getBody())) {
					// 套题
					quesBody = defaultQuestion.getMasterVersion().getBody();
					defaultQuestion.getMasterVersion().setBody(buildBody(quesBody, null));
				} else {
					DefaultQuestionUnit defaultQuestionUnit = (DefaultQuestionUnit) defaultQuestion.getMasterVersion()
							.getQuestionUnitList().get(0);
					quesBody = defaultQuestionUnit.getBody();
					defaultQuestionUnit.setBody(buildBody(quesBody, null));
					if (defaultQuestionUnit.getQuestionType() == QuestionType.SINGLE_CHOICE
							|| defaultQuestionUnit.getQuestionType() == QuestionType.MULTIPLE_CHOICE) {
						List<DefaultQuestionOption> questionOptionList = defaultQuestionUnit.getQuestionOptionList();
						if (questionOptionList != null && questionOptionList.size() > 0) {
							for (int i = 0; i < questionOptionList.size(); i++) {
								DefaultQuestionOption defaultQuestionOption = questionOptionList.get(i);
								defaultQuestionOption.setBody(buildBody(defaultQuestionOption.getBody(), null));
							}
						}
					}
				}
			}
		}
	}

	/**
	 * 给题目和选项添加url
	 *
	 * @param body
	 * @param playTime
	 * @return
	 */
	public String buildBody(String body, Integer playTime) {
		String[] bodyStrings = body.split("></a>");
		if (bodyStrings.length > 1) {
			String resultBody = "";
			for (int i = 0; i < bodyStrings.length; i++) {
				String containAStr = bodyStrings[i];
				if (containAStr.indexOf("<a") > -1) {
					String questionAudioId = matchAudioName(containAStr, "a", "id");
					QuestionAudio questionAudio = questionAudioService.findAudioById(questionAudioId);
					if (questionAudio != null) {
						// String url = sysProperty.getDomain() + questionAudio.getFileUrl();
						// 通用存储
						String url = FileStorageUtil.realPath(questionAudio.getFileUrl());
						if (playTime != null) {
							containAStr += " question-audio url=\"" + url + "\" playTime=\"" + playTime + "\""
									+ "></a>";
						} else {
							containAStr += " question-audio url=\"" + url + "\"" + "></a>";
						}
					}
				}
				resultBody += containAStr;
			}
			return resultBody;
		} else {
			return body;
		}
	}

	/**
	 * 获取一段html中某个标签的值
	 *
	 * @param source
	 * @param element
	 * @param attr
	 * @return
	 */
	private String matchAudioName(String source, String element, String attr) {
		String reg = "<" + element + "[^<>]*?\\s" + attr + "=['\"]?(.*?)['\"]?(\\s.*?)";
		Matcher m = Pattern.compile(reg).matcher(source);
		if (m.find()) {
			return m.group(1);
		}
		return "";
	}

	/**
	 * 检查所有题目是否为客观题
	 *
	 * @param paperDetailUnits
	 * @return
	 */
	private boolean checkIsAllQbjectiveQuestion(List<PaperDetailUnit> paperDetailUnits) {
		for (PaperDetailUnit paperDetailUnit : paperDetailUnits) {
			Question question = paperDetailUnit.getQuestion();
			// 填空或问答
			if (question.getQuestionType() == QuesStructType.FILL_BLANK_QUESTION
					|| question.getQuestionType() == QuesStructType.TEXT_ANSWER_QUESTION) {
				return false;
			}
			if (question.getQuestionType() == QuesStructType.NESTED_ANSWER_QUESTION) {
				List<Question> subQuestions = question.getSubQuestions();
				for (Question subQuestion : subQuestions) {
					if (subQuestion.getQuestionType() == QuesStructType.FILL_BLANK_QUESTION
							|| subQuestion.getQuestionType() == QuesStructType.TEXT_ANSWER_QUESTION) {
						return false;
					}
				}
			}
		}
		return true;
	}

	@Override
	public DefaultPaper getBaseDefaultPaper(String paperId) {
		Paper basePaper = Model.of(paperRepo.findById(paperId));
		if (basePaper == null) {
			LOG.error("该考试和课程下调卷规则中该类型试卷不存在,请检查调卷规则,调卷程序退出");
			throw new StatusException("Q-020560", "该考试和课程下调卷规则中试卷不存在,请重新制定调卷规则");
		}

		// 构建试卷结构
		DefaultPaper defaultPaper = this.buildDefaultByBasePaper(basePaper, null, null, null);
		return defaultPaper;
	}

	@Override
	public Map<String, DefaultQuestion> getDefaultQuestions(Set<String> questionIds) {
		Map<String, DefaultQuestion> map = new HashMap<>();
		List<Question> questions = quesRepo.findByIdIn(questionIds);
		if (CollectionUtils.isEmpty(questions)) {
			LOG.error("根据试题id的集合没有查询到试题结合");
			throw new StatusException("Q-020572", "根据试题id的集合没有查询到试题结合");
		}
		for (Question question : questions) {
			DefaultQuestion defaultQuestion = getDefaultQuestion(null, null, null, question.getId());
			map.put(question.getId(), defaultQuestion);
		}
		return map;
	}

	@Override
	public List<String> getAnswer(String questionId) {
		List<String> list = new ArrayList<>();
		Question question = Model.of(quesRepo.findById(questionId));

		if (question.getQuestionType() == QuesStructType.NESTED_ANSWER_QUESTION) {
			List<Question> subList = question.getSubQuestions();
			if (subList != null && subList.size() > 0) {
				String answer = "";
				for (Question subQuestion : subList) {
					if (subQuestion.getQuestionType() == QuesStructType.SINGLE_ANSWER_QUESTION
							|| subQuestion.getQuestionType() == QuesStructType.MULTIPLE_ANSWER_QUESTION) {
						String[] answers = QuestionAnswerConvert
								.parseQuestionOptionAnswers(subQuestion.getQuesOptions());
						answer = StringUtils.join(answers, ",");
					} else if (subQuestion.getQuestionType() == QuesStructType.BOOL_ANSWER_QUESTION) {
						if (subQuestion.getQuesAnswer().endsWith("正确")) {
							answer = "true";
						} else {
							answer = "false";
						}
					} else {
						answer = subQuestion.getQuesAnswer();
					}
					list.add(answer);
				}
			}
		} else {
			String answer = "";
			if (question.getQuestionType() == QuesStructType.SINGLE_ANSWER_QUESTION
					|| question.getQuestionType() == QuesStructType.MULTIPLE_ANSWER_QUESTION) {
				String[] answers = QuestionAnswerConvert.parseQuestionOptionAnswers(question.getQuesOptions());
				answer = StringUtils.join(answers, ",");
			} else if (question.getQuestionType() == QuesStructType.BOOL_ANSWER_QUESTION) {
				if (question.getQuesAnswer().endsWith("正确")) {
					answer = "true";
				} else {
					answer = "false";
				}
			} else {
				answer = question.getQuesAnswer();
			}
			list.add(answer);
		}

		return list;
	}

	@Override
	public String getQuestionStructure(String paperId) throws Exception {
		String json = paperService.findQuestionStructure(paperId);
		return json;
	}

}
