package com.qmth.themis.business.service.impl;

import java.io.File;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;

import javax.annotation.Resource;

import org.apache.commons.lang3.StringUtils;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.qmth.themis.business.cache.bean.ExamPaperCacheBean;
import com.qmth.themis.business.cache.bean.ObjectiveAnswerCacheBean;
import com.qmth.themis.business.config.SystemConfig;
import com.qmth.themis.business.constant.SpringContextHolder;
import com.qmth.themis.business.constant.SystemConstant;
import com.qmth.themis.business.dao.TEExamPaperMapper;
import com.qmth.themis.business.entity.TEExamPaper;
import com.qmth.themis.business.service.TEExamPaperService;
import com.qmth.themis.business.util.OssUtil;
import com.qmth.themis.common.exception.BusinessException;
import com.qmth.themis.common.util.FileUtil;

/**
 * @Description: 考试试卷 服务实现类
 * @Param:
 * @return:
 * @Author: wangliang
 * @Date: 2020/6/25
 */
@Service
public class TEExamPaperServiceImpl extends ServiceImpl<TEExamPaperMapper, TEExamPaper> implements TEExamPaperService {
    private static String underLine = "_";
    @Resource
    SystemConfig systemConfig;
    @Resource
    TEExamPaperMapper teExamPaperMapper;

    @Override
    public TEExamPaper findByExamIdAndCourseCodeAndPaperCode(Long examId, String courseCode, String paperCode) {
        if (examId == null) {
            throw new BusinessException("examId is null");
        }
        if (StringUtils.isBlank(courseCode)) {
            throw new BusinessException("courseCode is null");
        }
        if (StringUtils.isBlank(paperCode)) {
            throw new BusinessException("paperCode is null");
        }
        return teExamPaperMapper.findByExamIdAndCourseCodeAndPaperCode(examId, courseCode, paperCode);
    }

    @Cacheable(value = "exam_paper", key = "#paperId", unless = "#result == null")
    @Override
    public ExamPaperCacheBean getExamPaperCacheBean(Long paperId) {
        return cacheOperation(paperId);
    }

    /**
     * 更新试卷缓存
     *
     * @param paperId
     * @return
     */
    @Override
    @CachePut(value = "exam_paper", key = "#paperId", condition = "#result != null")
    public ExamPaperCacheBean updateExamPaperCacheBean(Long paperId) {
        return cacheOperation(paperId);
    }

    /**
     * 删除试卷缓存
     *
     * @param paperId
     */
    @Override
    @CacheEvict(value = "exam_paper", key = "#paperId")
    public void deleteExamPaperCacheBean(Long paperId) {

    }

    /**
     * 缓存操作
     *
     * @param paperId
     * @return
     */
    public ExamPaperCacheBean cacheOperation(Long paperId) {
        ExamPaperCacheBean ret = null;
        TEExamPaper ep = getById(paperId);
        if (ep == null) {
            return ret;
        }
        ret = new ExamPaperCacheBean();
        ret.setId(ep.getId());
        ret.setExamId(ep.getExamId());
        ret.setCourseCode(ep.getCourseCode());
        ret.setCode(ep.getCode());
        ret.setName(ep.getName());
        ret.setTotalScore(ep.getTotalScore());
        ret.setPaperPath(ep.getPaperPath());
        ret.setStructPath(ep.getStructPath());
        ret.setAnswerPath(ep.getAnswerPath());
        ret.setDecryptSecret(ep.getDecryptSecret());
        ret.setDecryptVector(ep.getDecryptVector());
        ret.setEncryptMode(ep.getEncryptMode());
        ret.setNeedVoiceAnswer(ep.getNeedVoiceAnswer());
        ret.setHasAudio(ep.getHasAudio());
        ret.setWeight(ep.getWeight());
        ret.setAudioPlayCount(ep.getAudioPlayCount());
        return ret;
    }
    /**
     * 删除客观题标答缓存
     *
     * @param paperId
     */
    @Override
    @CacheEvict(value = "objective_answer", key = "#paperId")
    public void deleteObjectiveAnswerCacheBean(Long paperId) {

    }
    @Cacheable(value = "objective_answer", key = "#paperId", unless = "#result == null")
    @Override
    public Map<String, ObjectiveAnswerCacheBean> getObjectiveAnswerCacheBean(Long paperId) {
        Map<String, ObjectiveAnswerCacheBean> ret = null;
        ExamPaperCacheBean ep = getExamPaperCacheBean(paperId);
        if (ep == null) {
            return ret;
        }
        ret = new HashMap<String, ObjectiveAnswerCacheBean>();
        String structUrl = OssUtil.getUrlForPrivateBucket(systemConfig.getOssEnv(3), ep.getStructPath());
        String answerUrl = OssUtil.getUrlForPrivateBucket(systemConfig.getOssEnv(3), ep.getAnswerPath());
        String tempDir = SystemConstant.TEMP_FILES_DIR;
        String dir = tempDir + "/" + uuid() + "/";
        File dfile = new File(dir);
        try {
            dfile.mkdirs();
            File structFile = new File(dir + "struct.json");
            FileUtil.saveUrlAsFile(structUrl, structFile);
//            File answerEncryptFile = new File(dir + "answer_encrypt_file.json");
//            FileUtil.saveUrlAsFile(answerUrl, answerEncryptFile);
            File answerFile = new File(dir + "answer_file.json");
            FileUtil.saveUrlAsFile(answerUrl, answerFile);
//            FileUtil.decryptFile(answerEncryptFile, answerFile, ep.getDecryptSecret(), ep.getDecryptVector());
            String structJson = FileUtil.readFileContent(structFile);
            String answerjson = FileUtil.readFileContent(answerFile);
            return buildCache(structJson, answerjson);
        } finally {
            FileUtil.deleteFolder(dir);
        }
    }


    private Map<String, ObjectiveAnswerCacheBean> buildCache(String structStr, String answerStr) {
        Map<String, ObjectiveAnswerCacheBean> map = new HashMap<String, ObjectiveAnswerCacheBean>();
        JSONObject answerJson = JSONObject.parseObject(answerStr);
        JSONArray answerdetails = answerJson.getJSONArray("details");
        JSONObject structJson = JSONObject.parseObject(structStr);
        JSONArray structdetails = structJson.getJSONArray("details");
        for (int i = 0; i < answerdetails.size(); i++) {
            Integer mainNum = answerdetails.getJSONObject(i).getInteger("number");
            JSONArray answerdetailquestions = answerdetails.getJSONObject(i).getJSONArray("questions");
            JSONArray structdetailquestions = structdetails.getJSONObject(i).getJSONArray("questions");
            for (int j = 0; j < answerdetailquestions.size(); j++) {
                JSONObject answerquestion = answerdetailquestions.getJSONObject(j);
                JSONObject structquestion = structdetailquestions.getJSONObject(j);
                Integer subNum = structquestion.getInteger("number");
                Double score = structquestion.getDouble("score");
                Integer structType = structquestion.getInteger("structType");
                if (structType.intValue() == 1
                        || structType.intValue() == 2
                        || structType.intValue() == 3) {
                    ObjectiveAnswerCacheBean bean = new ObjectiveAnswerCacheBean();
                    bean.setScore(score);
                    bean.setStructType(structType);
                    if (structType.intValue() == 1
                            || structType.intValue() == 2) {
                        JSONArray answer = answerquestion.getJSONArray("answer");
                        bean.setChoiceAnswer(answer);
                    }
                    if (structType.intValue() == 3) {
                        Boolean answer = answerquestion.getBoolean("answer");
                        bean.setBoolAnswer(answer);
                    }
                    map.put(mainNum + underLine + subNum, bean);
                }
                if (structType.intValue() == 6) {
                    JSONArray answersubQuestions = answerquestion.getJSONArray("subQuestions");
                    JSONArray structsubQuestions = structquestion.getJSONArray("subQuestions");
                    for (int k = 0; k < answersubQuestions.size(); k++) {
                        JSONObject answersubquestion = answersubQuestions.getJSONObject(k);
                        JSONObject structsubquestion = structsubQuestions.getJSONObject(k);
                        Integer subIndex = structsubquestion.getInteger("number");
                        Double subScore = structsubquestion.getDouble("score");
                        Integer subStructType = structsubquestion.getInteger("structType");

                        if (subStructType.intValue() == 1
                                || subStructType.intValue() == 2
                                || subStructType.intValue() == 3) {
                            ObjectiveAnswerCacheBean bean = new ObjectiveAnswerCacheBean();
                            bean.setScore(subScore);
                            bean.setStructType(subStructType);
                            if (subStructType.intValue() == 1
                                    || subStructType.intValue() == 2) {
                                JSONArray answer = answersubquestion.getJSONArray("answer");
                                bean.setChoiceAnswer(answer);
                            }
                            if (subStructType.intValue() == 3) {
                                Boolean answer = answersubquestion.getBoolean("answer");
                                bean.setBoolAnswer(answer);
                            }
                            map.put(mainNum + underLine + subNum + underLine + subIndex, bean);
                        }
                    }
                }
            }
        }
        return map;
    }

    private String uuid() {
        return UUID.randomUUID().toString().replaceAll("-", "");
    }

    @Override
    public List<TEExamPaper> findByExamIdAndCourseCode(Long examId, String courseCode) {
        return teExamPaperMapper.findListByExamIdAndCourseCode(examId, courseCode);
    }

    @Transactional
    @Override
    public void savePaperWeight(Map<Long, Double> map) {
    	TEExamPaperService examPaperService = SpringContextHolder.getBean(TEExamPaperService.class);
        for (Long id : map.keySet()) {
            teExamPaperMapper.updateWeight(id, map.get(id));
            examPaperService.deleteExamPaperCacheBean(id);
            examPaperService.deleteObjectiveAnswerCacheBean(id);
        }
    }
}
