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

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;

import javax.servlet.http.HttpServletRequest;

import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import net.sf.json.JsonConfig;

import org.apache.commons.lang.StringEscapeUtils;
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.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;

import cn.com.qmth.stmms.admin.utils.SessionExamUtils;
import cn.com.qmth.stmms.admin.vo.ExamInfoVO;
import cn.com.qmth.stmms.biz.exam.model.Exam;
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.query.ExamSearchQuery;
import cn.com.qmth.stmms.biz.exam.query.ExamStudentSearchQuery;
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.MarkerService;
import cn.com.qmth.stmms.biz.file.service.FileService;
import cn.com.qmth.stmms.biz.mark.model.PictureConfigItem;
import cn.com.qmth.stmms.biz.school.model.School;
import cn.com.qmth.stmms.biz.school.service.SchoolService;
import cn.com.qmth.stmms.biz.user.model.User;
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.ExamStatus;
import cn.com.qmth.stmms.common.enums.ExamType;
import cn.com.qmth.stmms.common.enums.LogType;
import cn.com.qmth.stmms.common.enums.MarkMode;
import cn.com.qmth.stmms.common.enums.ObjectiveStatus;
import cn.com.qmth.stmms.common.enums.Role;
import cn.com.qmth.stmms.common.utils.RequestUtils;

@Controller
@RequestMapping("/admin/exam")
public class ExamController extends BaseExamController {

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

    @Autowired
    private ExamService examService;

    @Autowired
    private ExamStudentService examStudentService;

    @Autowired
    private MarkerService markerService;

    @Autowired
    private ExamSubjectService examSubjectService;

    @Autowired
    private FileService fileService;

    @Autowired
    private SchoolService schoolService;

    @Autowired
    private ExamSubjectService subjectService;

    @Autowired
    private ExamStudentService studentService;

    @Logging(menu = "查询考试", type = LogType.QUERY)
    @RoleRequire(Role.SCHOOL_ADMIN)
    @RequestMapping(value = { "/list" })
    public String list(Model model, HttpServletRequest request, ExamSearchQuery query) {
        User user = RequestUtils.getWebUser(request).getUser();
        query.setSchoolId(user.getSchoolId());
        query.orderByIdDesc();
        query = examService.findByQuery(query);
        if (query.getCurrentCount() > 0) {
            model.addAttribute("examList", query.getResult());
        }
        model.addAttribute("statusList", ExamStatus.values());
        model.addAttribute("typeList", ExamType.values());
        model.addAttribute("query", query);
        return "modules/exam/examList";
    }

    @RequestMapping("/create")
    @RoleRequire(Role.SCHOOL_ADMIN)
    public String add(Exam exam, Model model) {
        model.addAttribute("exam", exam);
        model.addAttribute("statusList", ExamStatus.values());
        model.addAttribute("typeList", ExamType.values());
        model.addAttribute("markModeList", MarkMode.values());
        return "modules/exam/examForm";
    }

    @RequestMapping("/edit/{examId}")
    @RoleRequire(Role.SCHOOL_ADMIN)
    public String edit(@PathVariable Integer examId, Model model, ExamSearchQuery query) {
        Exam exam = examService.findById(examId);
        model.addAttribute("exam", exam);
        model.addAttribute("statusList", ExamStatus.values());
        model.addAttribute("pictureConfig", buildPictureConfig(exam.getSheetConfig()));
        model.addAttribute("passScore", exam.getPassScore());
        model.addAttribute("excellentScore", exam.getExcellentScore());
        model.addAttribute("markModeList", MarkMode.values());
        model.addAttribute("query", query);
        return "modules/exam/examEdit";
    }

    @Logging(menu = "创建考试", type = LogType.ADD)
    @RequestMapping(value = "/save", method = RequestMethod.POST)
    @RoleRequire(Role.SCHOOL_ADMIN)
    public String save(HttpServletRequest request, Exam exam, @RequestParam(required = false) Double passScore,
            @RequestParam(required = false) Double excellentScore, RedirectAttributes redirectAttributes) {
        User user = RequestUtils.getWebUser(request).getUser();
        exam.setSchoolId(user.getSchoolId());
        exam.setCreatorId(user.getId());
        exam.setStatus(ExamStatus.START);
        exam.setObjectiveStatus(ObjectiveStatus.WAITING);
        if (exam.getType().equals(ExamType.MULTI_MEDIA)) {
            exam.setForceSpecialTag(false);
        }
        JSONObject sasConfig = new JSONObject();
        sasConfig.accumulate("passScore", passScore);
        sasConfig.accumulate("excellentScore", excellentScore);
        exam.setSasConfig(sasConfig.toString());
        exam = examService.save(exam);
        addMessage(redirectAttributes, "创建考试'" + exam.getName() + "'成功");
        return "redirect:/admin/exam/list";
    }

    @Logging(menu = "编辑考试", type = LogType.UPDATE)
    @SuppressWarnings("unchecked")
    @RequestMapping(value = "/edit", method = RequestMethod.POST)
    @RoleRequire(Role.SCHOOL_ADMIN)
    public String edit(HttpServletRequest request, Exam exam, @RequestParam(required = false) String picList,
            @RequestParam(required = false) Double passScore, @RequestParam(required = false) Double excellentScore,
            ExamSearchQuery query, @RequestParam(required = false) ExamType queryType,
            @RequestParam(required = false) ExamStatus queryStatus) {
        User user = RequestUtils.getWebUser(request).getUser();
        Exam oldExam = examService.findById(exam.getId());
        if (oldExam != null && oldExam.getSchoolId().equals(user.getSchoolId())) {
            oldExam.setName(exam.getName());
            oldExam.setExamTime(exam.getExamTime());
            oldExam.setDescription(exam.getDescription());
            oldExam.setStatus(exam.getStatus());
            oldExam.setForceSpecialTag(exam.isForceSpecialTag());
            oldExam.setForbiddenInfo(exam.isForbiddenInfo());
            if (exam.isForbiddenInfo()) {
                oldExam.setForbiddenScore(exam.isForbiddenScore());
            } else {
                oldExam.setForbiddenScore(false);
            }
            oldExam.setEnableSplit(exam.isEnableSplit());
            oldExam.setAutoScroll(exam.isAutoScroll());
            oldExam.setShowReject(exam.isShowReject());
            JSONObject sasConfig = new JSONObject();
            sasConfig.accumulate("passScore", passScore);
            sasConfig.accumulate("excellentScore", excellentScore);
            oldExam.setSasConfig(sasConfig.toString());
            if (StringUtils.isNotBlank(picList)) {
                String sheetConfig = StringEscapeUtils.unescapeHtml(picList);
                JSONArray array = JSONArray.fromObject(sheetConfig);
                List<PictureConfigItem> list = JSONArray.toList(array, new PictureConfigItem(), new JsonConfig());
                oldExam.setSheetConfig(list == null ? null : StringUtils.join(list, PictureConfigItem.DB_ITEM_JOINER));
            }
            oldExam.setStartTime(exam.getStartTime());
            oldExam.setEndTime(exam.getEndTime());
            oldExam.setMarkMode(exam.getMarkMode());
            oldExam.setSheetView(exam.isSheetView());
            oldExam.setInspectScrollBottom(exam.getInspectScrollBottom());
            oldExam.setInspectUnrepeated(exam.getInspectUnrepeated());
            oldExam.setShowObjectiveScore(exam.getShowObjectiveScore());
            oldExam.setRemarkCount(exam.getRemarkCount());
            examService.save(oldExam);
        }
        return "redirect:/admin/exam/list?pageNumber=" + query.getPageNumber() + "&type=" + queryType + "&status="
                + queryStatus;
    }

    @Logging(menu = "考试详情", type = LogType.QUERY)
    @RequestMapping("/view/{examId}")
    public String view(Model model, HttpServletRequest request, @PathVariable Integer examId) {
        Exam exam = examService.findById(examId);
        long studentCount = examStudentService.countByExamId(exam.getId());
        long subjectCount = examSubjectService.count(examId);
        // long markerCount = markerService.countByExam(exam.getId());
        long scanCount = examStudentService.countByExamIdAndUpload(examId, true);
        long markedCount = examStudentService.countByExamIdAndSubjectiveScoreListIsNotNull(examId);
        long sheetCount = studentCount == 0 ? 0 : examStudentService.countSheetCountByExamId(examId);

        List<ExamInfoVO> voList = new ArrayList<ExamInfoVO>();

        ExamInfoVO student = new ExamInfoVO();
        student.setName("考生");
        student.setAttr("共导入 " + studentCount + " 个考生");
        student.setUrl("/admin/exam/student");

        ExamInfoVO subject = new ExamInfoVO();
        subject.setName("科目");
        subject.setAttr("共导入 " + subjectCount + " 个科目");
        subject.setUrl("/admin/exam/paper");

        // ExamInfoVO marker = new ExamInfoVO();
        // marker.setName("评卷员");
        // marker.setAttr("已创建 " + markerCount + " 个评卷员");
        // marker.setUrl("/admin/exam/marker");

        ExamInfoVO scan = new ExamInfoVO();
        scan.setName("扫描进度");
        scan.setAttr("已扫描 " + scanCount + " 个考生");
        scan.setUrl("/admin/exam/scan");

        ExamInfoVO sheet = new ExamInfoVO();
        sheet.setName("扫描张数");
        long sheetCount2 = new BigDecimal(sheetCount).divide(new BigDecimal(2), 0, BigDecimal.ROUND_HALF_UP)
                .longValue();
        sheet.setAttr("已扫描 " + sheetCount2 + " 张");
        sheet.setUrl("/admin/exam/scan");

        ExamInfoVO mark = new ExamInfoVO();
        mark.setName("评卷进度");
        mark.setAttr("已评完 " + markedCount + " 个考生");
        mark.setUrl("/admin/exam/mark");

        voList.add(student);
        voList.add(subject);
        voList.add(scan);
        voList.add(sheet);
        voList.add(mark);
        model.addAttribute("exam", exam);
        model.addAttribute("list", voList);
        return "modules/exam/examInfo";
    }

    @RequestMapping("/getSheetConfig")
    @RoleRequire(Role.SCHOOL_ADMIN)
    public String get(HttpServletRequest request, Model model, RedirectAttributes redirectAttributes,
            @RequestParam Integer examId, @RequestParam(required = false) String subjectCode) {
        Exam exam = examService.findById(examId);
        ExamSubject subject = examSubjectService.find(examId, subjectCode);
        ExamStudentSearchQuery query = new ExamStudentSearchQuery();
        query.setExamId(examId);
        query.setSubjectCode(subjectCode);
        query.setUpload(true);
        List<ExamStudent> examStudents = examStudentService.findByQuery(query).getResult();
        if (examStudents.size() > 0) {
            model.addAttribute("picUrls", buildPicUrl(examStudents.get(0)));
            String sheetConfig = subject != null ? subject.getSheetConfig() : exam.getSheetConfig();
            model.addAttribute("pictureConfig", buildPictureConfig(sheetConfig));
            model.addAttribute("fileServer", fileService.getFileServer());
            return "modules/mark/picConfig";
        } else {
            model.addAttribute("message", "没有已上传的考生");
            return "modules/mark/picConfig";
        }
    }

    private List<String> buildPicUrl(ExamStudent student) {
        return fileService.getSheetUris(student.getExamId(), student.getExamNumber(), 1, student.getSheetCount());
    }

    @RoleRequire({ Role.SCHOOL_ADMIN, Role.SUBJECT_HEADER, Role.SCHOOL_VIEWER, Role.INSPECTOR, Role.COLLEGE_ADMIN })
    @RequestMapping(value = "/select")
    public String select(Model model, HttpServletRequest request) {
        WebUser wu = RequestUtils.getWebUser(request);
        User user = RequestUtils.getWebUser(request).getUser();
        List<Exam> examList = new ArrayList<Exam>();
        if (wu.isSubjectHeader() || wu.isInspector()) {
            examList = examService.findBySubjectHeaderUserId(user.getSchoolId(), user.getId());
        } else if (wu.isSchoolViewer()) {
            examList = examService.findBySchoolViewUserId(user.getSchoolId(), user.getId());
        } else {
            examList = examService.findBySchoolId(user.getSchoolId());
        }
        model.addAttribute("examList", examList);
        SessionExamUtils.clearExamId(request);
        return "modules/exam/examSelect";
    }

    @RoleRequire({ Role.SCHOOL_ADMIN, Role.SUBJECT_HEADER, Role.SCHOOL_VIEWER, Role.INSPECTOR, Role.COLLEGE_ADMIN })
    @RequestMapping(value = "/select", method = RequestMethod.POST)
    public String selectExam(HttpServletRequest request, @RequestParam Integer examId) {
        Exam exam = examService.findById(examId);
        SessionExamUtils.setExamId(request, exam);
        return "redirect:/admin/home";
    }

    @RoleRequire({ Role.SCHOOL_ADMIN, Role.SUBJECT_HEADER, Role.SCHOOL_VIEWER, Role.INSPECTOR, Role.COLLEGE_ADMIN })
    @RequestMapping(value = "view/{examId}/export", method = RequestMethod.GET)
    public String exportExam(Model model, HttpServletRequest request, @PathVariable Integer examId) {
        Exam exam = examService.findById(examId);
        School school = schoolService.findById(exam.getSchoolId());
        model.addAttribute("schoolName", school.getName());
        model.addAttribute("year", Calendar.getInstance().get(Calendar.YEAR));
        model.addAttribute("subjectCount", subjectService.count(examId));
        model.addAttribute("studentCount", studentService.countByExamId(examId));
        model.addAttribute("sheetCount", studentService.countSheetCountByExamId(examId) / 2);
        return "modules/exam/examExport";
    }
}
