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

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import cn.com.qmth.examcloud.commons.exception.StatusException;
import cn.com.qmth.examcloud.core.questions.base.enums.PaperSeqMode;
import cn.com.qmth.examcloud.core.questions.base.question.enums.QuesStructType;
import cn.com.qmth.examcloud.core.questions.dao.ExportServiceManageRepo;
import cn.com.qmth.examcloud.core.questions.dao.entity.ExportServiceManage;
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.bean.dto.PaperDetailExp;
import cn.com.qmth.examcloud.core.questions.service.bean.dto.PaperDetailUnitExp;
import cn.com.qmth.examcloud.core.questions.service.export.ExportPaperAbstractService;
import cn.com.qmth.examcloud.question.commons.core.question.AnswerType;
import cn.com.qmth.examcloud.web.support.SpringContextHolder;

public class PaperUtil {

	private static ExportServiceManageRepo exportServiceManageRepo = SpringContextHolder
			.getBean(ExportServiceManageRepo.class);

	public static ExportPaperAbstractService getByServiceName(String serviceName) {
		if (SpringContextHolder.containsBean(serviceName)) {
			return (ExportPaperAbstractService) SpringContextHolder.getBean(serviceName);
		}
		return (ExportPaperAbstractService) SpringContextHolder.getBean("exportPaperAbstractService");

	}

	public static ExportPaperAbstractService getByRootOrgId(String rootOrgId) {
		ExportServiceManage esm = exportServiceManageRepo.findByOrgId(rootOrgId);
		if (esm == null) {
			return (ExportPaperAbstractService) SpringContextHolder.getBean("exportPaperAbstractService");
		} else {
			if (SpringContextHolder.containsBean(esm.getExportServiceName())) {
				return (ExportPaperAbstractService) SpringContextHolder.getBean(esm.getExportServiceName());
			}
			return (ExportPaperAbstractService) SpringContextHolder.getBean("exportPaperAbstractService");
		}
	}

	public static void setQuestionSeq(List<PaperDetailExp> paperDetailExps, PaperSeqMode seqMode) {
		if (paperDetailExps == null || paperDetailExps.size() == 0) {
			return;
		}
		if (PaperSeqMode.MODE1.equals(seqMode)) {
			setQuestionSeqMode1(paperDetailExps);
		} else if (PaperSeqMode.MODE2.equals(seqMode)) {
			setQuestionSeqMode2(paperDetailExps);
		} else if (PaperSeqMode.MODE4.equals(seqMode)) {
			setQuestionSeqMode4(paperDetailExps);
		} else {
			setQuestionSeqMode3(paperDetailExps);
		}
	}

	private static void disposeQuestion(List<PaperDetailExp> paperDetailExps) {
		for (PaperDetailExp paperDetail : paperDetailExps) {
			boolean nested = false;
			Set<Long> questionTypes = new HashSet<>();
			for (PaperDetailUnitExp paperDetailUnit : paperDetail.getPaperDetailUnits()) {
				// 如果是套题
				if (paperDetailUnit.getQuestionType().getName().equals("套题")) {
					nested = true;
					questionTypes.add(getTypeForNestedQuestion(paperDetailUnit));
				} else {
					Long questionTypeId = paperDetailUnit.getQuestionType().getId();
					questionTypes.add(questionTypeId);
				}
			}
			paperDetail.setQuestionTypes(new ArrayList<>(questionTypes));
			paperDetail.setNested(nested);
		}
	}

	private static void setQuestionSeqMode1(List<PaperDetailExp> paperDetailExps) {
		disposeQuestion(paperDetailExps);
		Map<Long, Integer> objectiveSeqMap = new HashMap<>();
		for (PaperDetailExp paperDetail : paperDetailExps) {
			int subjectiveSeq = 0;
			if (paperDetail.getQuestionTypes().size() == 1) {
				Long type = paperDetail.getQuestionTypes().get(0);
				if (QuesStructType.SINGLE_ANSWER_QUESTION.getId().longValue() == type.longValue()
						|| QuesStructType.MULTIPLE_ANSWER_QUESTION.getId().longValue() == type.longValue()
						|| QuesStructType.BOOL_ANSWER_QUESTION.getId().longValue() == type.longValue()) {// 客观题
					Integer objectiveSeq = objectiveSeqMap.get(type);
					if (objectiveSeq == null) {
						objectiveSeq = 0;
					}
					for (PaperDetailUnitExp unit : paperDetail.getPaperDetailUnits()) {
						if (unit.getQuestion().getSubQuestions() != null
								&& unit.getQuestion().getSubQuestions().size() > 0) {// 套题
							for (Question ques : unit.getQuestion().getSubQuestions()) {
								objectiveSeq++;
								ques.setQuestionSeq(objectiveSeq);
							}
						} else {
							objectiveSeq++;
							unit.getQuestion().setQuestionSeq(objectiveSeq);
						}
					}
					objectiveSeqMap.put(type, objectiveSeq);
				} else {
					for (PaperDetailUnitExp unit : paperDetail.getPaperDetailUnits()) {
						if (unit.getQuestion().getSubQuestions() != null
								&& unit.getQuestion().getSubQuestions().size() > 0) {// 套题
							for (Question ques : unit.getQuestion().getSubQuestions()) {
								subjectiveSeq++;
								ques.setQuestionSeq(subjectiveSeq);
							}
						} else {
							subjectiveSeq++;
							unit.getQuestion().setQuestionSeq(subjectiveSeq);
						}
					}
				}
			} else {// 混合型大题
				for (PaperDetailUnitExp unit : paperDetail.getPaperDetailUnits()) {
					if (unit.getQuestion().getSubQuestions() != null
							&& unit.getQuestion().getSubQuestions().size() > 0) {// 套题
						for (Question ques : unit.getQuestion().getSubQuestions()) {
							subjectiveSeq++;
							ques.setQuestionSeq(subjectiveSeq);
						}
					} else {
						subjectiveSeq++;
						unit.getQuestion().setQuestionSeq(subjectiveSeq);
					}
				}
			}
		}
	}

	private static void setQuestionSeqMode2(List<PaperDetailExp> paperDetailExps) {
		disposeQuestion(paperDetailExps);
		int objectiveSeq = 0;
		for (PaperDetailExp paperDetail : paperDetailExps) {
			int subjectiveSeq = 0;
			if (paperDetail.getQuestionTypes().size() == 1) {
				Long type = paperDetail.getQuestionTypes().get(0);
				if (QuesStructType.SINGLE_ANSWER_QUESTION.getId().longValue() == type.longValue()
						|| QuesStructType.MULTIPLE_ANSWER_QUESTION.getId().longValue() == type.longValue()
						|| QuesStructType.BOOL_ANSWER_QUESTION.getId().longValue() == type.longValue()) {// 客观题
					for (PaperDetailUnitExp unit : paperDetail.getPaperDetailUnits()) {
						if (unit.getQuestion().getSubQuestions() != null
								&& unit.getQuestion().getSubQuestions().size() > 0) {// 套题
							for (Question ques : unit.getQuestion().getSubQuestions()) {
								objectiveSeq++;
								ques.setQuestionSeq(objectiveSeq);
							}
						} else {
							objectiveSeq++;
							unit.getQuestion().setQuestionSeq(objectiveSeq);
						}
					}
				} else {
					for (PaperDetailUnitExp unit : paperDetail.getPaperDetailUnits()) {
						if (unit.getQuestion().getSubQuestions() != null
								&& unit.getQuestion().getSubQuestions().size() > 0) {// 套题
							for (Question ques : unit.getQuestion().getSubQuestions()) {
								subjectiveSeq++;
								ques.setQuestionSeq(subjectiveSeq);
							}
						} else {
							subjectiveSeq++;
							unit.getQuestion().setQuestionSeq(subjectiveSeq);
						}
					}
				}
			} else {// 混合型大题
				for (PaperDetailUnitExp unit : paperDetail.getPaperDetailUnits()) {
					if (unit.getQuestion().getSubQuestions() != null
							&& unit.getQuestion().getSubQuestions().size() > 0) {// 套题
						for (Question ques : unit.getQuestion().getSubQuestions()) {
							subjectiveSeq++;
							ques.setQuestionSeq(subjectiveSeq);
						}
					} else {
						subjectiveSeq++;
						unit.getQuestion().setQuestionSeq(subjectiveSeq);
					}
				}
			}
		}
	}

	private static void setQuestionSeqMode3(List<PaperDetailExp> paperDetailExps) {
		for (PaperDetailExp paperDetail : paperDetailExps) {
			int seq = 0;
			for (PaperDetailUnitExp unit : paperDetail.getPaperDetailUnits()) {
				if (unit.getQuestion().getSubQuestions() != null && unit.getQuestion().getSubQuestions().size() > 0) {// 套题
					for (Question ques : unit.getQuestion().getSubQuestions()) {
						seq++;
						ques.setQuestionSeq(seq);
					}
				} else {
					seq++;
					unit.getQuestion().setQuestionSeq(seq);
				}
			}
		}
	}

	private static void setQuestionSeqMode4(List<PaperDetailExp> paperDetailExps) {
		for (PaperDetailExp paperDetail : paperDetailExps) {
			int seq = 0;
			for (PaperDetailUnitExp unit : paperDetail.getPaperDetailUnits()) {
				if (unit.getQuestion().getSubQuestions() != null && unit.getQuestion().getSubQuestions().size() > 0) {// 套题
					int subseq = 0;
					for (Question ques : unit.getQuestion().getSubQuestions()) {
						subseq++;
						ques.setQuestionSeq(subseq);
					}
				} else {
					seq++;
					unit.getQuestion().setQuestionSeq(seq);
				}
			}
		}
	}

	public static List<PaperDetailExp> sortPaperDetailExps(List<PaperDetailExp> paperDetailExps) {
		if (paperDetailExps == null || paperDetailExps.size() == 0) {
			return null;
		}
		for (PaperDetailExp paperDetail : paperDetailExps) {
			boolean nested = false;
			Set<Long> questionTypes = new HashSet<>();
			for (PaperDetailUnitExp paperDetailUnit : paperDetail.getPaperDetailUnits()) {
				// 如果是套题
				if (paperDetailUnit.getQuestionType().getName().equals("套题")) {
					nested = true;
					questionTypes.add(getTypeForNestedQuestion(paperDetailUnit));
				} else {
					Long questionTypeId = paperDetailUnit.getQuestionType().getId();
					questionTypes.add(questionTypeId);
				}
			}
			paperDetail.setQuestionTypes(new ArrayList<>(questionTypes));
			paperDetail.setNested(nested);
		}

		Map<Long, List<PaperDetailExp>> baseMap = new LinkedHashMap<>();

		Map<Long, List<PaperDetailExp>> objectiveNestedMap = new HashMap<>();

		int index = 0;

		for (PaperDetailExp paperDetail : paperDetailExps) {
			index++;
			if (paperDetail.getQuestionTypes().size() == 1) {
				Long type = paperDetail.getQuestionTypes().get(0);
				if (QuesStructType.SINGLE_ANSWER_QUESTION.getId().longValue() == type.longValue()
						|| QuesStructType.MULTIPLE_ANSWER_QUESTION.getId().longValue() == type.longValue()
						|| QuesStructType.BOOL_ANSWER_QUESTION.getId().longValue() == type.longValue()) {// 客观题
					List<PaperDetailExp> list = baseMap.get(type);
					if (list == null) {
						list = new ArrayList<>();
						baseMap.put(type, list);
					}
					if (paperDetail.isNested()) {// 套题类客观题
						List<PaperDetailExp> nestedlist = objectiveNestedMap.get(type);
						if (nestedlist == null) {
							nestedlist = new ArrayList<>();
							objectiveNestedMap.put(type, nestedlist);
						}
						nestedlist.add(paperDetail);
					} else {
						list.add(paperDetail);
					}
				} else {
					List<PaperDetailExp> list = new ArrayList<>();
					list.add(paperDetail);
					baseMap.put(100L + index, list);
				}
			} else {// 混合型大题
				List<PaperDetailExp> list = new ArrayList<>();
				list.add(paperDetail);
				baseMap.put(100L + index, list);
			}
		}
		if (objectiveNestedMap.size() > 0) {
			for (Long type : objectiveNestedMap.keySet()) {
				baseMap.get(type).addAll(objectiveNestedMap.get(type));
			}
		}

		List<PaperDetailExp> ret = new ArrayList<>();
		for (List<PaperDetailExp> pds : baseMap.values()) {
			pds.get(0).setResetSubQuesSeq(true);
			ret.addAll(pds);
		}
		return ret;
	}

	public static void sortDetails(List<PaperDetail> paperDetails) {
		for (PaperDetail paperDetail : paperDetails) {
			boolean nested = false;
			Set<Long> questionTypes = new HashSet<>();
			for (PaperDetailUnit paperDetailUnit : paperDetail.getPaperDetailUnits()) {
				// 如果是套题
				if (paperDetailUnit.getQuestionType().getName().equals("套题")) {
					nested = true;
					questionTypes.add(getTypeForNestedQuestion(paperDetailUnit));
				} else {
					Long questionTypeId = paperDetailUnit.getQuestionType().getId();
					questionTypes.add(questionTypeId);
				}
			}
			// 如果全是同样的类型
			if (questionTypes.size() == 1) {
				for (Long l : questionTypes) {
					paperDetail.setSortNumber(l);
				}
			} else {
				paperDetail.setSortNumber(7L);
			}
			if (nested) {
				paperDetail.setSortNumberSub(2);
			} else {
				paperDetail.setSortNumberSub(1);
			}
		}
		Collections.sort(paperDetails, new Comparator<PaperDetail>() {
			@Override
			public int compare(PaperDetail o1, PaperDetail o2) {
				if (o1.getSortNumber() > o2.getSortNumber()) {
					return 1;
				} else if (o1.getSortNumber() < o2.getSortNumber()) {
					return -1;
				} else {
					if (o1.getSortNumberSub() > o2.getSortNumberSub()) {
						return 1;
					} else if (o1.getSortNumberSub() < o2.getSortNumberSub()) {
						return -1;
					} else {
						return 0;
					}
				}

			}
		});
		if (paperDetails != null && paperDetails.size() > 0) {
			// 循环所有大题，给小题重设题号
			int number = 0;
			for (PaperDetail paperDetail : paperDetails) {
				for (PaperDetailUnit paperDetailUnit : paperDetail.getPaperDetailUnits()) {
					number++;
					paperDetailUnit.setNumber(number);
				}
			}
		}
	}

	private static Long getTypeForNestedQuestion(PaperDetailUnitExp paperDetailUnit) {
		// 得到套题下面所有小题
		List<Question> questions = paperDetailUnit.getQuestion().getSubQuestions();
		Set<Long> subQuestionType = new HashSet<>();
		for (Question subQuestion : questions) {
			subQuestionType.add(subQuestion.getQuestionType().getId());
		}
		// 如果全是同样的类型
		if (subQuestionType.size() == 1) {
			for (Long l : subQuestionType) {
				return l;
			}
			return null;
		} else {
			return paperDetailUnit.getQuestionType().getId();
		}
	}

	private static Long getTypeForNestedQuestion(PaperDetailUnit paperDetailUnit) {
		// 得到套题下面所有小题
		List<Question> questions = paperDetailUnit.getQuestion().getSubQuestions();
		Set<Long> subQuestionType = new HashSet<>();
		for (Question subQuestion : questions) {
			subQuestionType.add(subQuestion.getQuestionType().getId());
		}
		// 如果全是同样的类型
		if (subQuestionType.size() == 1) {
			for (Long l : subQuestionType) {
				return l;
			}
			return null;
		} else {
			return paperDetailUnit.getQuestionType().getId();
		}
	}

	public static String getPaperChangeInfo(Double total, Integer dc, Integer uc, Paper now) {
		StringBuilder sb = new StringBuilder();
		if (total.doubleValue() != now.getTotalScore().doubleValue()) {
			sb.append(" 试卷总分变动(" + total + "变为" + now.getTotalScore() + ")");
		}
		if (dc.intValue() != now.getPaperDetailCount().intValue()) {
			sb.append(" 试卷大题数量变动(" + dc + "变为" + now.getPaperDetailCount() + ")");
		}
		if (uc.intValue() != now.getUnitCount().intValue()) {
			sb.append(" 试卷小题数量变动(" + uc + "变为" + now.getUnitCount() + ")");
		}
		if (sb.length() == 0) {
			return null;
		}
		return sb.toString();
	}

	public static Boolean isObjecttive(QuesStructType type) {
		if (QuesStructType.SINGLE_ANSWER_QUESTION.equals(type) || QuesStructType.MULTIPLE_ANSWER_QUESTION.equals(type)
				|| QuesStructType.BOOL_ANSWER_QUESTION.equals(type)) {
			return true;
		} else {
			return false;
		}
	}
	
	public static void checkUpdate(PaperDetailUnitExp updateUnit,PaperDetailUnit baseUnit,String msg) {
    	Question baseQuestion = baseUnit.getQuestion();
        Question updateQuestion = updateUnit.getQuestion();
    	if (baseUnit.getQuestionType() == QuesStructType.NESTED_ANSWER_QUESTION) {
            if (updateQuestion.getId().equals(baseQuestion.getId())) {
            	return;
            } else {
                int size = baseQuestion.getSubQuestions().size();
                // 判断更新的对象是哪个子题
                for (int index = 1; index <= size; index++) {

                    Question sub = baseQuestion.getSubQuestions().get(index - 1);
                    if (updateQuestion.getId().equals(sub.getId())) {
                    	if(updateQuestion.getScore().doubleValue()!=baseUnit.getSubScoreList().get(index - 1).doubleValue()) {
//                    		throw new StatusException("500", msg+"不能修改分数");
                    	}
                        checkUpdate(updateQuestion, sub,msg);

                    }
                }
            }
        } else {
        	if(updateUnit.getScore().doubleValue()!=baseUnit.getScore().doubleValue()) {
//        		throw new StatusException("500", msg+"不能修改分数");
        	}
        	checkUpdate(updateQuestion, baseQuestion,msg);
        }
    }
	public static void checkUpdate(Question update,Question base,String msg) {
    	if(QuesStructType.SINGLE_ANSWER_QUESTION.equals(base.getQuestionType())
    			||QuesStructType.MULTIPLE_ANSWER_QUESTION.equals(base.getQuestionType())){
	    	if(update.getQuesOptions().size()!=base.getQuesOptions().size()) {
	    		throw new StatusException("500", msg+"不能修改选项数量");
	    	}
    	}
    	if(QuesStructType.SINGLE_ANSWER_QUESTION.equals(base.getQuestionType())
    			||QuesStructType.MULTIPLE_ANSWER_QUESTION.equals(base.getQuestionType())
    			||QuesStructType.BOOL_ANSWER_QUESTION.equals(base.getQuestionType())){
	    	if(!update.getQuesAnswer().equals(base.getQuesAnswer())) {
//	    		throw new StatusException("500", msg+"不能修改客观题答案");
	    	}
    	}
    	if(!answerTypeEquals(update.getAnswerType(),base.getAnswerType())) {
    		throw new StatusException("500", msg+"不能修改作答类型");
    	}
    }
	
	private static boolean answerTypeEquals(AnswerType now,AnswerType old) {
		if(now==null&&old==null) {
			return true;
		}
		if(now==null&&old!=null) {
			return false;
		}
		if(AnswerType.DIVERSIFIED_TEXT.equals(now)&&old==null) {
			return true;
		}
		return now.equals(old);
	}
    
    public static void checkUpdateOption(PaperDetailUnitExp updateUnit,PaperDetailUnit baseUnit,String msg) {
    	Question baseQuestion = baseUnit.getQuestion();
        Question updateQuestion = updateUnit.getQuestion();
    	if (baseUnit.getQuestionType() == QuesStructType.NESTED_ANSWER_QUESTION) {
            if (updateQuestion.getId().equals(baseQuestion.getId())) {
            	return;
            } else {
                int size = baseQuestion.getSubQuestions().size();
                // 判断更新的对象是哪个子题
                for (int index = 1; index <= size; index++) {

                    Question sub = baseQuestion.getSubQuestions().get(index - 1);
                    if (updateQuestion.getId().equals(sub.getId())) {
                    	checkUpdateOption(updateQuestion, sub,msg);

                    }
                }
            }
        } else {
        	checkUpdateOption(updateQuestion, baseQuestion,msg);
        }
    }
    
    public static void checkUpdateOption(Question update,Question base,String msg) {
    	if(QuesStructType.SINGLE_ANSWER_QUESTION.equals(base.getQuestionType())
    			||QuesStructType.MULTIPLE_ANSWER_QUESTION.equals(base.getQuestionType())){
	    	if(update.getQuesOptions().size()!=base.getQuesOptions().size()) {
	    		throw new StatusException("500", msg+"不能修改选项数量");
	    	}
    	}
    	if(!answerTypeEquals(update.getAnswerType(),base.getAnswerType())) {
    		throw new StatusException("500", msg+"不能修改作答类型");
    	}
    }

}
