package com.qmth.qrzk.repository.quartz;

import java.io.File;
import java.io.FileFilter;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;

import com.qmth.qrzk.repository.common.base.BaseDao;
import com.qmth.qrzk.repository.user.model.Code;
import com.qmth.qrzk.repository.user.model.Question;
import com.qmth.qrzk.repository.user.model.QuestionOption;
import com.qmth.qrzk.repository.user.model.SysParam;
import com.qmth.qrzk.repository.user.model.User;
import com.qmth.qrzk.repository.user.service.ICodeSerivce;
import com.qmth.qrzk.repository.user.service.IUserService;
import com.qmth.qrzk.repository.user.service.impl.AttachmentService;
import com.qmth.qrzk.repository.user.service.impl.QuestionOptionServiceImpl;
import com.qmth.qrzk.repository.user.service.impl.QuestionServiceImpl;
import com.qmth.qrzk.repository.user.service.impl.SysParamService;
import com.qmth.qrzk.repository.utils.BeanHelper;
import com.qmth.qrzk.repository.utils.Consts;
import com.qmth.qrzk.repository.utils.DateHelper;
import com.qmth.qrzk.repository.utils.General;
import com.qmth.qrzk.repository.utils.ParamUtils;
import com.qmth.qrzk.repository.utils.docx.HtmlCreator;

@Service
public class LoadParamsQuartz {
	private static final Logger log = Logger.getLogger(LoadParamsQuartz.class);

	@Autowired
	private BaseDao dao;
	
	@Autowired
	private SysParamService sysParamService;
	
	@Autowired
	private IUserService userService;

	@Autowired
	private QuestionServiceImpl questionService;

	@Autowired
	private AttachmentService attachmentService;
	
	@Autowired
	private QuestionOptionServiceImpl quesOptService;

	@Autowired
	@Qualifier("codeServiceImpl")
	private ICodeSerivce codeSerivce;
	
	public void loadParamsAndCache(){
		loadSysParams();
		loadUsers();
		loadCodeTextMap();
		initCourseLastIndexMap();
	}
	
	public void loadBaseData(){
		loadSysParams();
		loadUsers();
		loadCodeTextMap();
		releaseTmpFolder();
		releaseOverdueAtts();
	}
	
	private void loadSysParams(){
		log.info("--开始加载系统配置信息，" + DateHelper.toLongString() + "...");
		Map<String, Object> map = new HashMap<String, Object>();
		try {
			for (SysParam t : sysParamService.getAllSysParams()) {
				map.put(t.getParamName(), t.getParamValue());
			}
			BeanHelper.setStaticField(ParamUtils.class, map);
			log.info("--加载系统配置信息完成。");
			General.initSysDir();
		} catch (Exception e) {
			log.error("加载系统配置信息失败，原因：" + e.getMessage(),e);
		}
	}
	
	/**
	 * 初始化用户信息
	 * 
	 */
	private void loadUsers(){
		log.info("--开始加载用户信息，" + DateHelper.toLongString() + "...");
		try{
			List<User> users=userService.queryUsers(null);
			for(User user:users){
				user.setPassword("");
				Consts.UserMap.put(user.getId(), user);
			}
			log.info("--加载用户信息完成。");
		}catch(Exception e){
			log.error("加载用户信息失败，原因：" + e.getMessage(),e);
		}
	}
	
	/**
	 * 清空临时文件夹。清空超过半天的临时文件（夹）
	 */
	private void releaseTmpFolder(){
		log.info("--开始清空临时文件夹（" + ParamUtils.TemporaryDirPath + "），" + DateHelper.toLongString() + "...");
		try{
			File tmpFolder = new File(ParamUtils.TemporaryDirPath);
			File[] tmps = tmpFolder.listFiles(new FileFilter() {
				@Override
				public boolean accept(File file) {//找出超过半天的文件（夹）
					return (System.currentTimeMillis() - file.lastModified() >= Consts.OVERDUE_TIME_MILLIS);
				}
			});
			for(File file:tmps){
				General.delete(file);
			}
			log.info("--清空临时文件夹完成，共清空：" + tmps.length + "个文件（夹）。");
		}catch(Exception e){
			log.error("清空临时文件夹失败，原因：" + e.getMessage(),e);
		}
	}
	
	/**
	 * 清空过期的附件(草稿状态)
	 */
	private void releaseOverdueAtts(){
		log.info("--开始清空过期的附件，" + DateHelper.toLongString() + "...");
		try{
			int deletedAttsNum = attachmentService.releaseOverdueAtts(new Date(System.currentTimeMillis() - Consts.OVERDUE_TIME_MILLIS));
			log.info("--清空过期的附件完成，共清空：" + deletedAttsNum + "个过期附件。");
		}catch(Exception e){
			e.printStackTrace();
			log.error("清空过期的附件失败，原因：" + e.getMessage(),e);
		}
	}
	
	/**
	 * 处理Lucene索引文件
	 
	public void loadLuceneIndex(){
		File file=new File(ParamUtils.LuceneIndexURL);
		//springmvc 是通过注入
//		IQuestionService question=new QuestionServiceImpl();
		
		List<Question> list=questionService.findAll();
		
		//1.课程  2.教材  3.层次 4.预计难度  5.题型  6认知层次 7.状态需要处理的
		
		SimpleLuceneDB db=new SimpleLuceneDB(file.getPath());
		try {
			db.open(true);
		} catch (IOException e) {
			e.printStackTrace();
		}
		
		
		List<Document> documents=new ArrayList<Document>();
		DocumentsUtil.Question2Document(list, documents);
		try {
			db.addDocument(documents);
		} catch (CorruptIndexException e1) {
			e1.printStackTrace();
		} catch (IOException e1) {
			e1.printStackTrace();
		}
		try {
			db.commit();
			db.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	*/
	
	public void repairQuestionData(){
		String nullSummary = " ";
		log.info("--开始修复数据不完整的试题及选项，" + DateHelper.toLongString() + "...");
		int quesNum = 0;
		int optNum = 0;
		long cur = System.currentTimeMillis();
		for(Integer quesId : questionService.findAllQuestionIds()){
			Question ques = questionService.searchQuestionWithOptionsById(quesId);
			if(ques == null){
				continue;
			}
			boolean hasModified = false;
			if(ques.getBodyWord() != null && ques.getBodyWord().length > 0 && General.isEmpty(ques.getBody())){
				try{
					ques.setBody(HtmlCreator.covertToHtml(ques.getBodyWord()).toString());
					ques.setBodySummary(null);
					hasModified = true;
				}catch(Exception e){
					log.warn("试题[id=" + ques.getId() + "]的word数据无法转换成html代码，原因：" + e.getMessage(), e);
				}
			}else if ((ques.getBodyWord() == null || ques.getBodyWord().length == 0) && General.isNotEmpty(ques.getBody())) {
				try{
					ques.setBodyWord(General.htmlToDocx(ques.getBody()));
					ques.setBodySummary(null);
					hasModified = true;
				}catch(Exception e){
					log.warn("试题[id=" + ques.getId() + "]的html代码无法转换成word数据，原因：" + e.getMessage(), e);
				}
			}
			if(General.isNotEmpty(ques.getBody()) && General.isEmpty(ques.getBodySummary())){
				try{
					ques.setBodySummary(General.extractText(ques.getBody()));
					if(General.isEmpty(ques.getBodySummary())){
						ques.setBodySummary(nullSummary);
					}
					hasModified = true;
				}catch(Exception e){
					log.warn("试题[id=" + ques.getId() + "]提取纯文本失败，原因：" + e.getMessage(), e);
				}
			}

			if(ques.getAnswerWord() != null && ques.getAnswerWord().length > 0 && General.isEmpty(ques.getAnswer())){
				try{
					ques.setAnswer(HtmlCreator.covertToHtml(ques.getAnswerWord()).toString());
					ques.setAnswerSummary(null);
					hasModified = true;
				}catch(Exception e){
					log.warn("试题[id=" + ques.getId() + "]的word答案无法转换成html代码，原因：" + e.getMessage(), e);
				}
			}else if ((ques.getAnswerWord() == null || ques.getAnswerWord().length == 0) && General.isNotEmpty(ques.getAnswer())) {
				try{
					ques.setAnswerWord(General.htmlToDocx(ques.getAnswer()));
					ques.setAnswerSummary(null);
					hasModified = true;
				}catch(Exception e){
					log.warn("试题[id=" + ques.getId() + "]的html代码答案无法转换成word数据，原因：" + e.getMessage(), e);
				}
			}
			if(General.isNotEmpty(ques.getAnswer()) && General.isEmpty(ques.getAnswerSummary())){
				try{
					ques.setAnswerSummary(General.extractText(ques.getAnswer()));
					if(General.isEmpty(ques.getAnswerSummary())){
						ques.setAnswerSummary(nullSummary);
					}
					hasModified = true;
				}catch(Exception e){
					log.warn("试题[id=" + ques.getId() + "]的答案提取纯文本失败，原因：" + e.getMessage(), e);
				}
			}
			if(hasModified){
				try{
					questionService.update(ques);
					quesNum++;
					log.info("成功修复试题[id=" + ques.getId() + "]数据.");
				}catch(Exception e){
					log.warn("更新试题[id=" + ques.getId() + "]失败，原因：" + e.getMessage(), e);
				}
			}
			
			if(ques.getOptions() != null){
				for(QuestionOption qo:ques.getOptions()){
					boolean optHasModified = false;
					if(qo.getContentWord() != null && qo.getContentWord().length > 0 && General.isEmpty(qo.getContent())){
						try{
							qo.setContent(HtmlCreator.covertToHtml(qo.getContentWord()).toString());
							qo.setSummary(null);
							optHasModified = true;
						}catch(Exception e){
							log.warn("试题[id=" + ques.getId() + "]下面的的选项[id=" + qo.getId() + "]word数据无法转换成html代码，原因：" + e.getMessage(), e);
						}
					}else if ((qo.getContentWord() == null || qo.getContentWord().length == 0) && General.isNotEmpty(qo.getContent())) {
						try{
							qo.setContentWord(General.htmlToDocx(qo.getContent()));
							qo.setSummary(null);
							optHasModified = true;
						}catch(Exception e){
							log.warn("试题[id=" + ques.getId() + "]下面的的选项[id=" + qo.getId() + "]html代码无法转换成word数据，原因：" + e.getMessage(), e);
						}
					}
					if(General.isNotEmpty(qo.getContent()) && General.isEmpty(qo.getSummary())){
						try{
							qo.setSummary(General.extractText(qo.getContent()));
							if(General.isEmpty(qo.getSummary())){
								qo.setSummary(nullSummary);
							}
							optHasModified = true;
						}catch(Exception e){
							log.warn("试题[id=" + ques.getId() + "]下面的的选项[id=" + qo.getId() + "]提取纯文本失败，原因：" + e.getMessage(), e);
						}
					}
					if(optHasModified){
						try{
							quesOptService.update(qo);
							optNum++;
							log.info("成功修复选项[id=" + qo.getId() + "]数据.");
						}catch(Exception e){
							log.warn("更新选项[id=" + qo.getId() + "]失败，原因：" + e.getMessage(), e);
						}
					}
				}
			}
		}
		log.info("--修复数据不完整的试题及选项完成，共修复试题：" + quesNum + "个，选项：" + optNum + "个，耗时：" + (System.currentTimeMillis() - cur)/1000.0 + "s.");
	}
	
	/**
	 * 初始化课程最大的题号索引值Map
	 */
	public void initCourseLastIndexMap(){
		log.info("--开始初始化课程最大的题号索引值Map，" + DateHelper.toLongString() + "...");
		List<Map<String,Object>> statList = dao.getList("statMaxIndexByCourseCode");
		for(Map<String,Object> stat:statList){
			String courseCode = (String) stat.get("code");
			int lastIndex = General.toInteger(stat.get("lastIndex"), 0);
			Consts.CourseLastIndexMap.put(courseCode, lastIndex);
			log.info(courseCode + "\t" + lastIndex);
		}
		log.info("--初始化课程最大的题号索引值Map完成。");
	}
	
	/**
	 * 加载字典值显示值字典，key为itemType-itemCode，value为itemValue。
	 */
	public void loadCodeTextMap(){
		log.info("--开始加载字典值显示值字典，" + DateHelper.toLongString() + "...");
		List<Code> codes = codeSerivce.getAllCode();
		for(Code c:codes){
			Consts.CodeTextMap.put(c.getItemType() + "-" + c.getItemCode(), c.getItemValue());
		}
		log.info("--加载字典值显示值字典完成。");
	}
}
