package cn.com.qmth.stmms.admin.exam;

import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;

import cn.com.qmth.stmms.biz.exam.model.Exam;
import cn.com.qmth.stmms.biz.exam.model.ExamQuestion;
import cn.com.qmth.stmms.biz.exam.model.ExamStudent;
import cn.com.qmth.stmms.biz.exam.model.ExamSubject;
import cn.com.qmth.stmms.biz.exam.model.MarkGroup;
import cn.com.qmth.stmms.biz.exam.service.ExamQuestionService;
import cn.com.qmth.stmms.biz.exam.service.ExamService;
import cn.com.qmth.stmms.biz.exam.service.ExamStudentService;
import cn.com.qmth.stmms.biz.exam.service.ExamSubjectService;
import cn.com.qmth.stmms.biz.exam.service.MarkGroupService;
import cn.com.qmth.stmms.biz.lock.LockService;
import cn.com.qmth.stmms.biz.mark.model.MarkLibrary;
import cn.com.qmth.stmms.biz.mark.model.ProblemHistory;
import cn.com.qmth.stmms.biz.mark.model.ProblemType;
import cn.com.qmth.stmms.biz.mark.query.ProblemHistorySearchQuery;
import cn.com.qmth.stmms.biz.mark.service.MarkLibraryService;
import cn.com.qmth.stmms.biz.mark.service.MarkService;
import cn.com.qmth.stmms.biz.mark.service.ProblemHistoryService;
import cn.com.qmth.stmms.biz.mark.service.ProblemTypeService;
import cn.com.qmth.stmms.biz.user.model.User;
import cn.com.qmth.stmms.biz.user.service.UserService;
import cn.com.qmth.stmms.common.annotation.Logging;
import cn.com.qmth.stmms.common.annotation.RoleRequire;
import cn.com.qmth.stmms.common.domain.WebUser;
import cn.com.qmth.stmms.common.enums.HistoryStatus;
import cn.com.qmth.stmms.common.enums.LibraryStatus;
import cn.com.qmth.stmms.common.enums.LockType;
import cn.com.qmth.stmms.common.enums.LogType;
import cn.com.qmth.stmms.common.enums.MarkStatus;
import cn.com.qmth.stmms.common.enums.Role;
import cn.com.qmth.stmms.common.utils.DateUtils;
import cn.com.qmth.stmms.common.utils.RequestUtils;

@Controller
@RequestMapping("/admin/exam/problem/history")
public class ProblemHistoryController extends BaseExamController {

    protected static Logger log = LoggerFactory.getLogger(ProblemHistoryController.class);

    public static HistoryStatus[] STATUS_LIST = { HistoryStatus.WAITING, HistoryStatus.BACK };

    @Autowired
    private ProblemTypeService problemService;

    @Autowired
    private ProblemHistoryService historyService;

    @Autowired
    private ExamStudentService studentService;

    @Autowired
    private ExamSubjectService subjectService;

    @Autowired
    private ExamService examService;

    @Autowired
    private MarkGroupService groupService;

    @Autowired
    private ExamQuestionService questionService;

    @Autowired
    private UserService userService;

    @Autowired
    private MarkLibraryService libraryService;

    @Autowired
    private LockService lockService;

    @Autowired
    private MarkService markService;

    @Logging(menu = "问题卷查询", type = LogType.QUERY)
    @RequestMapping
    public String list(HttpServletRequest request, Model model, ProblemHistorySearchQuery query) {
        WebUser wu = RequestUtils.getWebUser(request);
        int examId = getSessionExamId(request);
        List<ProblemType> problemTypes = problemService.findByExamId(examId);
        Map<Integer, ProblemType> problemMap = new HashMap<Integer, ProblemType>();
        for (ProblemType problemType : problemTypes) {
            problemMap.put(problemType.getId(), problemType);
        }
        if (wu.isSubjectHeader() && StringUtils.isBlank(query.getSubjectCode())) {
            String subjectCodeIn = StringUtils.join(wu.getSubjectCodeSet(), ",");
            query.setSubjectCodeIn(subjectCodeIn);
        }
        if (query.getStatus() == null) {
            query.setStatus(HistoryStatus.WAITING);
        }
        query.setExamId(examId);
        query.orderByExamNumber();
        query = historyService.findByQuery(query);

        List<ExamStudent> list = new LinkedList<ExamStudent>();
        for (ProblemHistory history : query.getResult()) {
            ExamStudent student = studentService.findById(history.getStudentId());
            student.setNumber(history.getGroupNumber());
            student.setProblemType(problemMap.get(history.getProblemId()));
            student.setLibraryId(history.getLibraryId());
            if (history.getMarkerId() != null) {
                User user = userService.findByMarkerId(history.getMarkerId());
                student.setMarkLogin(user.getLoginName() + " " + user.getName());
                student.setMarkTime(DateUtils.formatDateTime(history.getCreateTime()));
            }
            if (history.getUserId() != null) {
                User user = userService.findById(history.getUserId());
                student.setProblemUserName(user.getLoginName() + " " + user.getName());
                student.setProblemRestTime(DateUtils.formatDateTime(history.getUpdateTime()));
            }
            list.add(student);
        }
        model.addAttribute("resultList", list);
        model.addAttribute("statusList", STATUS_LIST);
        model.addAttribute("query", query);
        model.addAttribute("subjectList", getProblemSubject(examId, wu));
        model.addAttribute("problemList", problemTypes);
        List<MarkGroup> groupList = groupService.findByExamAndSubjectAndStatus(examId, query.getSubjectCode(),
                MarkStatus.FORMAL);
        for (MarkGroup group : groupList) {
            List<ExamQuestion> questions = questionService.findByExamAndSubjectAndObjectiveAndGroupNumber(examId,
                    group.getSubjectCode(), false, group.getNumber());
            group.setQuestionList(questions);
        }
        model.addAttribute("groupList", groupList);
        Exam exam = examService.findById(examId);
        model.addAttribute("examType", exam.getType());
        return "modules/exam/problemHistory";
    }

    private List<ExamSubject> getProblemSubject(int examId, WebUser wu) {
        List<ExamSubject> list = new LinkedList<ExamSubject>();
        List<String> codes = historyService.findProblemSubjectCode(examId);
        List<ExamSubject> subjects = getExamSubject(examId, wu);
        for (ExamSubject examSubject : subjects) {
            if (codes.contains(examSubject.getCode())) {
                list.add(examSubject);
            }
        }
        return list;
    }

    @Logging(menu = "任务批量重置", type = LogType.QUERY)
    @RequestMapping("/restBatch")
    @RoleRequire({ Role.SCHOOL_ADMIN, Role.SUBJECT_HEADER, Role.COLLEGE_ADMIN })
    public String restBatch(HttpServletRequest request, Model model, RedirectAttributes redirectAttributes,
            @RequestParam Integer[] libraryIds) {
        WebUser wu = RequestUtils.getWebUser(request);
        for (Integer libraryId : libraryIds) {
            MarkLibrary library = libraryService.findById(libraryId);
            if (library != null && subjectCheck(library.getSubjectCode(), RequestUtils.getWebUser(request))) {
                try {
                    lockService.watch(LockType.EXAM_SUBJECT, library.getExamId(), library.getSubjectCode());
                    lockService.watch(LockType.GROUP, library.getExamId(), library.getSubjectCode(),
                            library.getGroupNumber());
                    lockService.waitlock(LockType.STUDENT, library.getStudentId());
                    if (library.getStatus().equals(LibraryStatus.PROBLEM)) {
                        markService.rejectLibrary(library, wu.getId(), null, true);
                    }
                } catch (Exception e) {
                    log.error("back library error", e);
                } finally {
                	lockService.unlock(LockType.STUDENT, library.getStudentId());
                    lockService.unwatch(LockType.GROUP, library.getExamId(), library.getSubjectCode(),
                            library.getGroupNumber());
                    lockService.unwatch(LockType.EXAM_SUBJECT, library.getExamId(), library.getSubjectCode());
                }
            }
        }
        return "redirect:/admin/exam/problem/history";
    }
}
