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

import java.io.File;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import cn.com.qmth.examcloud.core.questions.base.Model;
import org.apache.commons.lang3.StringUtils;
import org.docx4j.XmlUtils;
import org.docx4j.jaxb.Context;
import org.docx4j.wml.Body;
import org.docx4j.wml.P;
import org.docx4j.wml.R;
import org.docx4j.wml.Text;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import cn.com.qmth.examcloud.core.questions.base.question.enums.QuesStructType;
import cn.com.qmth.examcloud.api.commons.security.bean.User;

import com.google.gson.Gson;

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.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.dao.entity.ExamPaper;
import cn.com.qmth.examcloud.core.questions.dao.entity.ExportStructure;
import cn.com.qmth.examcloud.core.questions.dao.entity.ExtractConfig;
import cn.com.qmth.examcloud.core.questions.dao.entity.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.QuestionTypeNum;
import cn.com.qmth.examcloud.core.questions.service.PaperDetailService;
import cn.com.qmth.examcloud.core.questions.service.PaperDetailUnitService;
import cn.com.qmth.examcloud.core.questions.service.PaperService;
import cn.com.qmth.examcloud.core.questions.dao.QuesRepo;
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.base.BeanCopierUtil;
import cn.com.qmth.examcloud.core.questions.base.CommonUtils;
import cn.com.qmth.examcloud.core.questions.base.enums.ExamFileType;
import cn.com.qmth.examcloud.core.questions.base.enums.ExportType;
import cn.com.qmth.examcloud.core.questions.base.exception.PaperException;
import cn.com.qmth.examcloud.core.questions.base.word.DocxProcessUtil;

/**
 * @author chenken
 * @date 2017年7月31日 上午9:04:53
 * @company QMTH
 * @description 石油大学导出、上传文件service
 */
@Service("sydxExportPaperService")
public class SydxExportPaperService extends ExportPaperAbstractService {
    @Autowired
    PaperRepo paperRepo;

    @Autowired
    PaperDetailRepo paperDetailRepo;

    @Autowired
    PaperDetailUnitRepo paperDetailUnitRepo;

    @Autowired
    QuesRepo quesRepo;

    @Autowired
    Gson gson;

    @Autowired
    PaperDetailUnitService paperDetailUnitService;

    @Autowired
    PaperService paperService;

    @Autowired
    private PaperDetailService paperDetailService;

    @Override
    public void downloadPaper(String paperId, String zipFileName, String examType) throws Exception {
        PaperExp paperExp = initExportSydxPaper(paperId);
        if (paperExp != null) {
            String paperfileName = paperExp.getCourseNo() + "_" + ExamFileType.PAPER.getName() + DOCX_SUFFIX;
            File file = new File(TEMP_FILE_EXP + File.separator + zipFileName + File.separator + paperfileName);
            DocxProcessUtil.exportWordNew(paperExp, file, SYDX_TEMPLATE_PAPER);
            DocxProcessUtil.processImage(zipFileName + File.separator + paperfileName, getPkgList(paperId));
        }

    }

    @Override
    public void downloadPaperAnswer(String paperId, String zipFileName) throws Exception {
        PaperExp paperExp = initExportSydxPaper(paperId);
        if (paperExp != null) {
            String paperfileName = paperExp.getCourseNo() + "_" + ExamFileType.ANSWER.getName() + DOCX_SUFFIX;
            File file = new File(TEMP_FILE_EXP + File.separator + zipFileName + File.separator + paperfileName);
            DocxProcessUtil.exportWordNew(paperExp, file, SYDX_TEMPLATE_ANSWER);
            DocxProcessUtil.processImage(zipFileName + File.separator + paperfileName, getPkgList(paperId));
        }

    }

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

    /**
     * 初始化导出石油大学试卷DTO
     *
     * @param id
     * @return
     */
    private PaperExp initExportSydxPaper(String id) throws Exception {
        //获取paper
        Paper paper = Model.of(paperRepo.findById(id));
        paperService.formatPaper(paper, null);
        if (paper == null) {
            throw new PaperException("该试卷不存在");
        }
        //创建paperDto
        PaperExp paperExp = BeanCopierUtil.copyProperties(paper, PaperExp.class);

        paperExp.setTitle(CommonUtils.PAPER_TITLE);
        paperExp.setSubTitle(CommonUtils.PAPER_SUB_TITLE);
        //获取大题
        List<PaperDetail> paperDetails = paperDetailRepo.findByPaperOrderByNumber(paper);
        List<PaperDetailExp> paperDetailExps = new ArrayList<PaperDetailExp>();
        for (PaperDetail paperDetail : paperDetails) {
            PaperDetailExp paperDetailExp = new PaperDetailExp();
            BeanUtils.copyProperties(paperDetail, paperDetailExp);
            paperDetailExps.add(paperDetailExp);
        }
        paperExp.setPaperDetails(paperDetailExps);
        //封装小题
        for (int i = 0; i < paperDetailExps.size(); i++) {
            PaperDetailExp paperDetailExp = paperDetailExps.get(i);
            paperDetailExp.setTitle(getDetailTitle(paperDetailExp));
            List<PaperDetailUnit> paperDetailUnits = paperDetailUnitRepo.findByPaperDetailOrderByNumber(paperDetails.get(i));
            setAnswerWord(paperDetailUnits);
            List<PaperDetailUnitExp> paperDetailUnitExps = new ArrayList<PaperDetailUnitExp>();
            for (PaperDetailUnit paperDetailUnit : paperDetailUnits) {
                PaperDetailUnitExp paperDetailUnitExp = new PaperDetailUnitExp();
                BeanUtils.copyProperties(paperDetailUnit, paperDetailUnitExp);
                paperDetailUnitExps.add(paperDetailUnitExp);
            }
            //选择题，套题下选择题  选项顺序重新排列
            paperService.reorderChoicequestionOption(paperDetailUnitExps);
            paperDetailExps.get(i).setPaperDetailUnits(paperDetailUnitExps);
        }
        //初始化试卷序号
        initPaperNum(paperExp);
        return paperExp;
    }

    /**
     * 设置客观题答案
     *
     * @param answer
     * @return
     * @throws Exception
     */
    private String getObjectAnswer(String answerWordMl, String answer) throws Exception {
        String tmpStr = DocxProcessUtil.BODY_HEADER + answerWordMl + 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();
            pContent.removeAll(pContent);
            R run = new R();
            Text text = new Text();
            text.setValue("[答案]:" + answer);
            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 answerWordMl
     * @return
     * @throws Exception
     */
    private String getSubjectAnswer(String answerWordMl) throws Exception {
        String tmpStr = DocxProcessUtil.BODY_HEADER + answerWordMl + 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("[答案]:");
            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();
    }

    private void setAnswerWord(List<PaperDetailUnit> paperDetailUnits) throws Exception {
        for (PaperDetailUnit paperDetailUnit : paperDetailUnits) {
            if (paperDetailUnit == null || paperDetailUnit.getQuestion() == null) {
                break;
            }
            String optionOrder = paperDetailUnit.getOptionOrder();
            Question question = paperDetailUnit.getQuestion();
            if (question.getQuestionType() == QuesStructType.SINGLE_ANSWER_QUESTION
                    || question.getQuestionType() == QuesStructType.MULTIPLE_ANSWER_QUESTION) {
                setAnswerWordUnit(question, optionOrder);
            } else if (question.getQuestionType() == QuesStructType.NESTED_ANSWER_QUESTION) {
                List<Question> subQuestions = question.getSubQuestions();
                int index = 0;
                for (int k = 0; k < subQuestions.size(); k++) {
                    Question subQuestion = subQuestions.get(k);
                    if (subQuestion.getQuestionType() == QuesStructType.SINGLE_ANSWER_QUESTION
                            || subQuestion.getQuestionType() == QuesStructType.MULTIPLE_ANSWER_QUESTION) {
                        if (StringUtils.isNotEmpty(optionOrder) && optionOrder.contains(";")) {
                            setAnswerWordUnit(subQuestion, optionOrder.split(";")[index]);
                        } else {
                            setAnswerWordUnit(subQuestion, "");
                        }
                        index++;
                    }
                }
            } else {
                question.setQuesAnswerWord(getSubjectAnswer(question.getQuesAnswerWord()));
            }
        }
    }

    private void setAnswerWordUnit(Question question, String optionOrder) throws Exception {
        List<QuesOption> quesOptions = question.getQuesOptions();
        if (quesOptions == null || quesOptions.size() == 0) {
            return;
        }
        if (StringUtils.isEmpty(optionOrder)) {
            int j = 0;
            String answer = "";
            for (QuesOption quesOption : quesOptions) {
                if (quesOption.getIsCorrect() == 1) {
                    answer += CommonUtils.getOptionNum(j);
                }
                j++;
            }
            question.setQuesAnswerWord(getObjectAnswer(question.getQuesAnswerWord(), answer));
        } else {
            String[] order = optionOrder.split(",");
            for (int i = 0; i < order.length; i++) {
                for (QuesOption quesOption : quesOptions) {
                    if (order[i].equals(quesOption.getNumber()) && quesOption.getIsCorrect() == 1) {
                        question.setQuesAnswerWord(getObjectAnswer(question.getQuesAnswerWord(), CommonUtils.getOptionNum(i)));
                    }
                }
            }
        }
    }

    public String getDetailTitle(PaperDetailExp paperDetailExp) {
        int totalScore = paperDetailExp.getScore().intValue();
        int count = paperDetailExp.getUnitCount();
        return "本大题共" + count + "小题,共" + totalScore + "分";
    }

    /**
     * 初始化序号
     *
     * @param paperExp
     */
    public void initPaperNum(PaperExp paperExp) throws Exception {
        if (paperExp.getPaperDetails() == null || paperExp.getPaperDetails().size() == 0) {
            return;
        }
        int mainNum = 0;
        int subNum = 0;
        Collections.sort(paperExp.getPaperDetails());
        for (PaperDetailExp paperDetail : paperExp.getPaperDetails()) {
            //大题序号
            paperDetail.setNumber(++mainNum);
            paperDetail.setCnNum(CommonUtils.toCHNum(paperDetail.getNumber()));
            if (paperDetail.getPaperDetailUnits() == null ||
                    paperDetail.getPaperDetailUnits().size() == 0) {
                continue;
            }
            //小题序号
            for (PaperDetailUnitExp paperDetailUnit : paperDetail.getPaperDetailUnits()) {
                List<QuesOption> optionList = paperDetailUnit.getQuestion().getQuesOptions();
                if (optionList != null && optionList.size() > 0) {
                    int index = 0;
                    for (QuesOption quesOption : optionList) {
                        quesOption.setOptionBodyWord(initPaperExpService.setOptionNum(quesOption.getOptionBodyWord(), initPaperExpService.getOptionNum(index)));
                        index++;
                    }
                }
                List<Question> subQuesList = paperDetailUnit.getQuestion().getSubQuestions();
                Question question = paperDetailUnit.getQuestion();
                //套题序号
                if (subQuesList != null && subQuesList.size() > 0) {
                    question.setQuesBodyWord(initPaperExpService.replaceQuesBlank(question.getQuesBodyWord(), subNum + 1));
                    for (Question subQues : subQuesList) {
                        int curSubNum = ++subNum;
                        subQues.setQuesBodyWord(initPaperExpService.setSubQuesNum(subQues.getQuesBodyWord(), curSubNum));
                        subQues.setQuesBodyWord(initPaperExpService.replaceQuesBlank(subQues.getQuesBodyWord(), curSubNum));
                        List<QuesOption> subOptionList = subQues.getQuesOptions();
                        if (subOptionList != null && subOptionList.size() > 0) {
                            int sub_index = 0;
                            for (QuesOption quesOption : subOptionList) {
                                quesOption.setOptionBodyWord(initPaperExpService.setOptionNum(quesOption.getOptionBodyWord(), initPaperExpService.getOptionNum(sub_index)));
                                sub_index++;
                            }
                        }
                    }
                } else {
                    int curSubNum = ++subNum;
                    question.setQuesBodyWord(initPaperExpService.setSubQuesNum(question.getQuesBodyWord(), curSubNum));
                    question.setQuesBodyWord(initPaperExpService.replaceQuesBlank(question.getQuesBodyWord(), curSubNum));
                }
            }
        }
    }


}
