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

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import cn.com.qmth.examcloud.commons.exception.StatusException;
import cn.com.qmth.examcloud.core.questions.base.BeanCopierUtil;
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.core.enums.CourseLevel;
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.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.Question;
import cn.com.qmth.examcloud.core.questions.service.ExamFileService;
import cn.com.qmth.examcloud.core.questions.service.PaperService;
import cn.com.qmth.examcloud.core.questions.service.bean.dto.DownloadPaperDto;
import cn.com.qmth.examcloud.core.questions.service.bean.dto.PaperDetailExp;
import cn.com.qmth.examcloud.core.questions.service.bean.dto.PaperDetailUnitExp;
import cn.com.qmth.examcloud.core.questions.service.bean.dto.PaperExp;
import cn.com.qmth.examcloud.core.questions.service.impl.CourseService;
import cn.com.qmth.examcloud.core.questions.service.util.PaperUtil;


/**
 * @author weiwenhai
 * @describle 初始化导出对象service
 * @date 2017.10.17
 */
@Service("initPaperExpService")
public class InitPaperExpService {

    @Autowired
    PaperRepo paperRepo;

    @Autowired
    PaperService paperService;

    @Autowired
    PaperDetailRepo paperDetailRepo;

    @Autowired
    PaperDetailUnitRepo paperDetailUnitRepo;

    @Autowired
    ExamFileService examFileService;


    @Autowired
    QuesRepo quesRepo;

    @Autowired
    AudioTimeConfigRepo audioTimeConfigRepo;

    @Autowired
    CourseService courseService;

//    @Autowired
//    private SysProperty sysProperty;

    public static final String FILL_BLANK_QUESTION_FLAG = "###";

    public static final String TEMP_FILE_EXP = "docxExport/";

    /**
     * Word文件后缀
     */
    public static final String DOCX_SUFFIX = ".docx";
    /**
     * Excel文件后缀
     */
    public static final String EXCEL_SUFFIX = ".xlsx";
    /**
     * ZIP文件后缀
     */
    public static final String ZIP_SUFFIX = ".zip";

    public static final String ENCODING = "UTF-8";

    /**
     * 根据paper得到导出试卷对象PaperExp
     */
    public PaperExp initPaperExp(DownloadPaperDto dto) {
        Paper paper = Model.of(paperRepo.findById(dto.getPaperId()));
        return this.initPaperExp(paper,dto);
    }

    /**
     * 根据paper得到导出试卷对象PaperExp
     */
    public PaperExp initPaperExp(Paper paper,DownloadPaperDto dto) {
        if (paper == null) {
            throw new StatusException("500", "该试卷不存在！");
        }

        Course course = courseService.getCourse(Long.valueOf(paper.getOrgId()), paper.getCourse().getCode());
        //Course course = courseService.getCourse(0L, paper.getCourse().getCode());//for export test

        //创建试卷导出的dto
        PaperExp paperExpDto = BeanCopierUtil.copyProperties(paper, PaperExp.class);
        if (paper.getCourse() == null) {
            paperExpDto.setCourseLevel(CourseLevel.ALL.getName());
        } else {
            paperExpDto.setCourseLevel(CourseLevel.getCourseLevel(paper.getCourse().getLevel()).getName());
        }

        //获取原试卷所有大题
        List<PaperDetail> paperDetails = paperDetailRepo.findByPaperOrderByNumber(paper);
        //生成新的大题对象集合，加添对应的小题
        List<PaperDetailExp> paperDetailExps = separatePaperDetailUntils(paperDetails, paperExpDto);
        //设置小题题序号
        PaperUtil.setQuestionSeq(paperDetailExps, dto.getSeqMode());
        //计算小题数量
        setPaperDetailExpsSeq(paperDetailExps);
        //给新的大题添加分数
        scorePaperDetailExps(paperDetailExps);

        paperExpDto.setPaperDetails(paperDetailExps);
        paperExpDto.getCourse().setId(course.getId());
        return paperExpDto;
    }

    /**
     * 将所有小题分类，添加到对应的大题下
     *
     * @param paperDetails
     * @return
     */
    private List<PaperDetailExp> separatePaperDetailUntils(List<PaperDetail> paperDetails, PaperExp paperExpDto) {
        List<PaperDetailExp> paperDetailExps = new ArrayList<>();
        //循环大题
        for (PaperDetail paperDetail : paperDetails) {
            //获取小题
            List<PaperDetailUnit> paperDetailUnits = paperDetailUnitRepo.findByPaperDetailOrderByNumber(paperDetail);
            //set集合用来将小题分类
            Set<Long> questionTypes = new HashSet<>();
            //大题的临时集合，用来区分原卷每个大题
            List<PaperDetailExp> subPaperDetailExps = new ArrayList<>();
            //第一次循环小题，分成大题类型
            for (PaperDetailUnit paperDetailUnit : paperDetailUnits) {
                //判断该试卷是否为音频试卷
                if (paperDetailUnit.getQuestion().getHasAudio() != null && paperDetailUnit.getQuestion().getHasAudio()) {
                    paperExpDto.setHasAudio(true);    //设置试卷含有音频
                }
                //如果是套题
                if (paperDetailUnit.getQuestionType().getName().equals("套题")) {
                    isSubQuestion(paperDetailUnit, questionTypes);
                } else {
                    Long questionTypeId = paperDetailUnit.getQuestionType().getId();
                    questionTypes.add(questionTypeId);
                }
            }
            //遍历Set，生成大题集合
            for (Long questionType : questionTypes) {
                //生成大题对象
                PaperDetailExp paperDetailExp = new PaperDetailExp();
                paperDetailExp.setSortNumber(questionType);
                if (StringUtils.isBlank(paperDetail.getName())) {
                    paperDetailExp.setName("默认大题");
                } else {
                    paperDetailExp.setName(paperDetail.getName());
                }
                subPaperDetailExps.add(paperDetailExp);
            }
            //第二次循环小题，添加到对应的大题下
            for (PaperDetailUnit paperDetailUnit : paperDetailUnits) {
                //判断是否为套题
                if (paperDetailUnit.getQuestionType().getName().equals("套题")) {
                    addSubQuestion(paperDetailUnit, subPaperDetailExps);
                } else {
                    PaperDetailUnitExp paperDetailUnitExp = BeanCopierUtil.copyProperties(paperDetailUnit, PaperDetailUnitExp.class);
                    //循环大题
                    for (PaperDetailExp paperDetailExp : subPaperDetailExps) {
                        if (paperDetailExp.getSortNumber().longValue() == paperDetailUnitExp.getQuestionType().getId().longValue()) {
                            List<PaperDetailUnitExp> paperDetailUnitExps = paperDetailExp.getPaperDetailUnits();
                            //如果大题下面没有小题，就生成新对象
                            if (paperDetailUnitExps == null) {
                                paperDetailUnitExps = new ArrayList<PaperDetailUnitExp>();
                            }
                            paperDetailUnitExps.add(paperDetailUnitExp);
                            //将小题添加到对应大题下面
                            paperDetailExp.setPaperDetailUnits(paperDetailUnitExps);
                        }
                    }
                }
            }
            paperDetailExps.addAll(subPaperDetailExps);
        }
        return paperDetailExps;
    }
    private void setPaperDetailExpsSeq(List<PaperDetailExp> paperDetailExps) {

        if (paperDetailExps != null && paperDetailExps.size() > 0) {
            //循环所有大题，给大题排序
            for (int i = 0; i < paperDetailExps.size(); i++) {
                Integer number = i + 1;
                paperDetailExps.get(i).setNumber(number);
                paperDetailExps.get(i).setCnNum(CommonUtils.toCHNum(number));
                int subNum = 0;
                //循环小题，判断是否存在套题
                for (PaperDetailUnitExp paperDetailUnitExp : paperDetailExps.get(i).getPaperDetailUnits()) {
                    //如果有套题
                    if (paperDetailUnitExp.getQuestionType().getName().equals("套题")) {
                        subNum = subNum + paperDetailUnitExp.getQuestion().getSubQuestions().size();
                    } else {
                        subNum = subNum + 1;
                    }
                }
                paperDetailExps.get(i).setUnitCount(subNum);
            }
        }
    }

    /**
     * 每个大题添加分数
     */
    private void scorePaperDetailExps(List<PaperDetailExp> paperDetailExps) {
        for (PaperDetailExp paperDetailExp : paperDetailExps) {
            List<PaperDetailUnitExp> paperDetailUnitExps = paperDetailExp.getPaperDetailUnits();
            Double totalScore = 0.0;
            //所有小题分数相加，得到大题分数
            for (PaperDetailUnitExp paperDetailUnitExp : paperDetailUnitExps) {
                totalScore += paperDetailUnitExp.getScore();
            }
            paperDetailExp.setScore(totalScore);
        }
    }

    /**
     * 校验大题下的小题分数是不是一样
     *
     * @param paperDetailExp
     * @return 如果分数一样，返回分数
     * 如果分数不一样，返回 null
     */
    public String checkPaperDetailUnitScore(PaperDetailExp paperDetailExp) {
        List<PaperDetailUnitExp> paperDetailUnitExps = paperDetailExp.getPaperDetailUnits();
        Set<Double> scoreSet = new HashSet<>();
        for (PaperDetailUnitExp unitExp : paperDetailUnitExps) {
            //判断套路
            if (unitExp.getQuestionType() == QuesStructType.NESTED_ANSWER_QUESTION) {
                List<Question> subQuestions = unitExp.getQuestion().getSubQuestions();
                for (Question subQuestion : subQuestions) {
                    scoreSet.add(subQuestion.getScore());
                }
				/*List<Double> subScoreList =  unitExp.getSubScoreList();
				for(Double score:subScoreList){
					scoreSet.add(score);
				}*/
            } else {
                scoreSet.add(unitExp.getScore());
            }
        }
        if (scoreSet.size() == 1) {
            return scoreSet.iterator().next() + "";
        }
        return null;
    }

    /**
     * 套题添加到对应的大题
     *
     * @param paperDetailUnit
     * @param subPaperDetailExps
     */
    private void addSubQuestion(PaperDetailUnit paperDetailUnit, List<PaperDetailExp> subPaperDetailExps) {
        PaperDetailUnitExp paperDetailUnitExp = BeanCopierUtil.copyProperties(paperDetailUnit, PaperDetailUnitExp.class);
        //得到套题下面所有小题
        List<Question> questions = paperDetailUnit.getQuestion().getSubQuestions();
        Set<Long> subQuestionType = new HashSet<>();
        for (Question subQuestion : questions) {
            subQuestionType.add(subQuestion.getQuestionType().getId());
        }
        //如果全是同样的类型
        if (subQuestionType.size() > 0 && subQuestionType.size() < 2) {
            //获取所有题目，添加到对应大题下面
            for (Long l : subQuestionType) {
                //循环已有的大题，进行添加套题
                for (PaperDetailExp paperDetailExp : subPaperDetailExps) {
                    if (paperDetailExp.getSortNumber().longValue() == l) {
                        List<PaperDetailUnitExp> paperDetailUnitExps = paperDetailExp.getPaperDetailUnits();
                        //如果大题下面没有小题，就生成新对象
                        if (paperDetailUnitExps == null) {
                            paperDetailUnitExps = new ArrayList<PaperDetailUnitExp>();
                        }
                        paperDetailUnitExps.add(paperDetailUnitExp);
                        //将小题添加到对应大题下面
                        paperDetailExp.setPaperDetailUnits(paperDetailUnitExps);
                    }
                }
            }
        } else {
            //循环大题
            for (PaperDetailExp paperDetailExp : subPaperDetailExps) {
                if (paperDetailExp.getSortNumber().longValue() == paperDetailUnitExp.getQuestionType().getId().longValue()) {
                    List<PaperDetailUnitExp> paperDetailUnitExps = paperDetailExp.getPaperDetailUnits();
                    //如果大题下面没有小题，就生成新对象
                    if (paperDetailUnitExps == null) {
                        paperDetailUnitExps = new ArrayList<PaperDetailUnitExp>();
                    }
                    paperDetailUnitExps.add(paperDetailUnitExp);
                    //将小题添加到对应大题下面
                    paperDetailExp.setPaperDetailUnits(paperDetailUnitExps);
                }
            }
        }
    }

    /**
     * 处理套题类型
     *
     * @param paperDetailUnit
     */
    private void isSubQuestion(PaperDetailUnit paperDetailUnit, Set<Long> questionType) {
        //得到套题下面所有小题
        List<Question> questions = paperDetailUnit.getQuestion().getSubQuestions();
        Set<Long> subQuestionType = new HashSet<>();
        for (Question subQuestion : questions) {
            subQuestionType.add(subQuestion.getQuestionType().getId());
        }
        //如果全是同样的类型
        if (subQuestionType.size() > 0 && subQuestionType.size() < 2) {
            for (Long l : subQuestionType) {
                questionType.add(l);
            }
        } else {
            Long questionTypeId = paperDetailUnit.getQuestionType().getId();
            questionType.add(questionTypeId);
        }
    }

    /**
     * 设置选项号
     *
     * @param optionWordMl
     * @param num
     * @return
     * @throws Exception
     */
//    public String setOptionNum(String optionWordMl, String num) throws Exception {
//        String tmpStr = DocxProcessUtil.BODY_HEADER + optionWordMl + DocxProcessUtil.BODY_TAIL;
//        Body body = (Body) XmlUtils.unmarshalString(tmpStr, Context.jc, Body.class);
//        List<Object> pList = body.getContent();
//        int index = 0;
//        for (Object pObj : pList) {
//            if (index > 0) {
//                break;
//            }
//            P p = (P) pObj;
//            List<Object> pContent = p.getContent();
//            R run = new R();
//            Text text = new Text();
//            text.setValue(num + ". ");
//            run.getContent().add(text);
//            pContent.add(0, run);
//            index++;
//        }
//        StringBuffer pWordMl = new StringBuffer();
//        for (Object pObj : pList) {
//            if (pObj instanceof P) {
//                pWordMl.append(DocxProcessUtil.formatPWordMl(XmlUtils.marshaltoString(pObj)));
//            }
//        }
//        return pWordMl.toString();
//    }

    /**
     * 将数字1,2,3,4转化成A,B,C,D
     *
     * @param number
     * @return
     */
    public String getOptionNum(int number) {
        char optionNum = (char) (65 + number);
        return String.valueOf(optionNum);
    }

    /**
     * 设置题号
     *
     * @param quesBodyWordMl
     * @param num
     * @return
     * @throws Exception
     */
//    public String setSubQuesNum(String quesBodyWordMl, int num) throws Exception {
//        String tmpStr = DocxProcessUtil.BODY_HEADER + quesBodyWordMl + DocxProcessUtil.BODY_TAIL;
//        Body body = (Body) XmlUtils.unmarshalString(tmpStr, Context.jc, Body.class);
//        List<Object> pList = body.getContent();
//        int index = 0;
//        for (Object pObj : pList) {
//            if (index > 0) {
//                break;
//            }
//            P p = (P) pObj;
//            List<Object> pContent = p.getContent();
//            R run = new R();
//            Text text = new Text();
//            text.setValue(num + ". ");
//            run.getContent().add(text);
//            pContent.add(0, run);
//            index++;
//        }
//        StringBuffer pWordMl = new StringBuffer();
//        for (Object pObj : pList) {
//            if (pObj instanceof P) {
//                pWordMl.append(DocxProcessUtil.formatPWordMl(XmlUtils.marshaltoString(pObj)));
//            }
//        }
//        return pWordMl.toString();
//    }

    /**
     * 替换填空
     * 将###替换为下划线_______
     *
     * @param wordMl
     * @param num
     * @return
     * @throws Exception
     */
//    public String replaceQuesBlank(String wordMl, int num) throws Exception {
//        String tmpStr = DocxProcessUtil.BODY_HEADER + wordMl + DocxProcessUtil.BODY_TAIL;
//        Body body = (Body) XmlUtils.unmarshalString(tmpStr, Context.jc, Body.class);
//        List<Object> pList = body.getContent();
//        int index = 0;
//        int cur = 0;
//        Map<Integer, String> curMap = new HashMap<>();
//        for (Object pObj : pList) {
//            if (pObj.getClass().equals(P.class)) {
//                List<Object> pContent = ((P) pObj).getContent();
//                for (Object rObj : pContent) {
//                    if (rObj.getClass().equals(R.class)) {
//                        List<Object> rContent = ((R) rObj).getContent();
//                        for (Object tObj : rContent) {
//                            if (tObj instanceof JAXBElement)
//                                tObj = ((JAXBElement<?>) tObj).getValue();
//                            if (tObj.getClass().equals(Text.class)) {
//                                Text text = (Text) tObj;
//                                String str = text.getValue();
//                                //1
//                                if ("##".equals(str.trim())) {
//                                    str = "___";
//                                    text.setValue(str);
//                                }
//                                //2
//                                str = str.replaceAll("###", "______");
//                                text.setValue(str);
//                                //3
//                                Pattern pattern = Pattern.compile("##\\d{1,}##");
//                                Matcher m = pattern.matcher(str);
//                                while (m.find()) {
//                                    int curNum = num + index;
//                                    String a = m.group();
//                                    str = str.replaceAll(a, "___" + (curNum) + "___");
//                                    text.setValue(str);
//                                    index++;
//                                }
//                                //4
//                                /*if(str.startsWith("#") || str.equals("___")){
//                                    curMap.put(cur,str);
//                                    text.setValue("");
//                                }*/
//                                //5
//                                if (str.matches("^\\d{1,}$")) {
//                                    String preStr = curMap.get(cur - 1);
//                                    int curNum = num + index;
//                                    if (!StringUtils.isEmpty(preStr) && preStr.startsWith("#")) {
//                                        text.setValue("___" + (curNum) + "___");
//                                    }
//                                    index++;
//                                }
//                                cur++;
//                            }
//                        }
//                    }
//                }
//            }
//        }
//        StringBuffer pWordMl = new StringBuffer();
//        for (Object pObj : pList) {
//            if (pObj instanceof P) {
//                pWordMl.append(DocxProcessUtil.formatPWordMl(XmlUtils.marshaltoString(pObj)));
//            }
//        }
//        return pWordMl.toString();
//    }

}
