package cn.com.qmth.stmms.api.controller;

import java.text.DecimalFormat;
import java.util.LinkedList;
import java.util.List;

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.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
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.bind.annotation.ResponseBody;

import cn.com.qmth.stmms.api.utils.AESUtil;
import cn.com.qmth.stmms.api.utils.MenualAbsentDTO;
import cn.com.qmth.stmms.biz.api.auth.annotation.AuthValidate;
import cn.com.qmth.stmms.biz.api.auth.exception.ApiException;
import cn.com.qmth.stmms.biz.campus.model.Campus;
import cn.com.qmth.stmms.biz.campus.service.CampusService;
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.ExamStudentPaper;
import cn.com.qmth.stmms.biz.exam.model.ExamSubject;
import cn.com.qmth.stmms.biz.exam.model.QuestionDetail;
import cn.com.qmth.stmms.biz.exam.model.QuestionUnit;
import cn.com.qmth.stmms.biz.exam.query.ExamStudentSearchQuery;
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.ExamStudentPaperService;
import cn.com.qmth.stmms.biz.exam.service.ExamStudentService;
import cn.com.qmth.stmms.biz.exam.service.ExamSubjectService;
import cn.com.qmth.stmms.biz.mark.model.MarkLibrary;
import cn.com.qmth.stmms.biz.mark.service.MarkLibraryService;
import cn.com.qmth.stmms.biz.user.model.User;
import cn.com.qmth.stmms.biz.utils.ScoreItem;
import cn.com.qmth.stmms.common.enums.LibraryStatus;
import cn.com.qmth.stmms.common.utils.RequestUtils;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;

@Controller("examStudentApiController")
@RequestMapping("/api")
public class ExamStudentController extends BaseApiController {

    protected static Logger logger = LoggerFactory.getLogger(ExamStudentController.class);

    @Autowired
    private ExamStudentService examStudentService;

    @Autowired
    private ExamService examService;

    @Autowired
    private CampusService campusService;

    @Autowired
    private ExamSubjectService examSubjectService;

    @Autowired
    private ExamQuestionService questionService;

    @Autowired
    private MarkLibraryService markLibraryService;

    @Autowired
    private ExamStudentPaperService studentPaperService;

    @AuthValidate("adminUser")
    @RequestMapping(value = "/student/manualAbsent/{examId}", method = RequestMethod.POST)
    @ResponseBody
    public Object updateManualAbsent(HttpServletRequest request, @PathVariable Integer examId,
            @RequestBody MenualAbsentDTO[] datas) {
        User user = RequestUtils.getApiUser(request);
        Exam exam = examService.findById(examId);
        if (exam != null && exam.getSchoolId().equals(user.getSchoolId())) {
            for (MenualAbsentDTO dto : datas) {
                examStudentService.updateManualAbsent(examId, dto.getExamNumber(), dto.isAbsent());
            }
            return true;
        } else {
            throw ApiException.EXAM_NOT_ACCESSIBLED;
        }
    }

    @AuthValidate("adminUser")
    @RequestMapping(value = "/student/manualAbsent/clear", method = RequestMethod.POST)
    @ResponseBody
    public Object clearManualAbsent(HttpServletRequest request, @RequestParam Integer examId) {
        User user = RequestUtils.getApiUser(request);
        Exam exam = examService.findById(examId);
        if (exam != null && exam.getSchoolId().equals(user.getSchoolId())) {
            examStudentService.clearManualAbsent(examId);
            return true;
        } else {
            throw ApiException.EXAM_NOT_ACCESSIBLED;
        }
    }

    @AuthValidate("adminUser")
    @RequestMapping("/exam/students/{examId}")
    @ResponseBody
    public JSONArray getExamStudents(HttpServletRequest request, @PathVariable Integer examId,
            @RequestParam(required = false) Integer pageNumber, @RequestParam(required = false) Integer pageSize) {
        User user = RequestUtils.getApiUser(request);
        JSONArray array = new JSONArray();
        Exam exam = examService.findById(examId);
        if (pageNumber == null || pageNumber < 1) {
            pageNumber = 1;
        }
        if (pageSize == null || pageSize < 1 || pageSize > 1000) {
            pageSize = 1000;
        }

        if (exam != null && exam.getSchoolId().equals(user.getSchoolId())) {
            List<ExamStudent> esList = examStudentService.findByExamId(examId, pageNumber, pageSize);
            for (ExamStudent student : esList) {
                JSONObject obj = new JSONObject();
                obj.accumulate("examNumber", student.getExamNumber());
                obj.accumulate("campusName", student.getCampusName());
                obj.accumulate("subjectCode", student.getSubjectCode());
                obj.accumulate("subjectName", student.getSubjectName());
                obj.accumulate("name", student.getName());
                obj.accumulate("studentId", String.valueOf(student.getId()));
                obj.accumulate("studentCode", student.getStudentCode());
                obj.accumulate("packageCode", student.getPackageCode());
                obj.accumulate("barcode", student.getExamNumber());

                Campus campus = campusService.findBySchoolAndName(exam.getSchoolId(), student.getCampusName());
                obj.accumulate("campusCode", campus != null ? campus.getId().toString() : "");
                array.add(obj);
            }
        }
        return array;
    }

    @AuthValidate("adminUser")
    @RequestMapping("/students/{examId}")
    @ResponseBody
    public JSONArray getStudent(HttpServletRequest request, @PathVariable Integer examId,
            @RequestParam(required = false) Boolean upload, @RequestParam(required = false) Boolean absent,
            @RequestParam(required = false) Integer pageNumber, @RequestParam(required = false) Integer pageSize) {
        User user = RequestUtils.getApiUser(request);
        JSONArray array = new JSONArray();
        Exam exam = examService.findById(examId);
        if (exam != null && exam.getSchoolId().equals(user.getSchoolId())) {
            ExamStudentSearchQuery query = new ExamStudentSearchQuery();
            query.setExamId(examId);
            query.setUpload(upload);
            query.setAbsent(absent);
            query.setPageNumber(pageNumber);
            query.setPageSize(pageSize);
            examStudentService.findByQuery(query);
            for (ExamStudent student : query.getResult()) {
                JSONObject obj = new JSONObject();
                obj.accumulate("id", student.getId());
                obj.accumulate("schoolId", student.getSchoolId());
                obj.accumulate("examNumber", student.getExamNumber());
                obj.accumulate("campusName", student.getCampusName());
                obj.accumulate("subjectCode", student.getSubjectCode());
                obj.accumulate("subjectName", student.getSubjectName());
                obj.accumulate("name", student.getName());
                obj.accumulate("studentCode", student.getStudentCode());
                obj.accumulate("packageCode", StringUtils.trimToEmpty(student.getPackageCode()));

                Campus campus = campusService.findBySchoolAndName(exam.getSchoolId(), student.getCampusName());
                obj.accumulate("campusCode", campus != null ? campus.getId().toString() : "");
                array.add(obj);
            }
        }
        return array;
    }

    @AuthValidate("adminUser")
    @RequestMapping("/students/count/{examId}")
    @ResponseBody
    public long getStudentCount(HttpServletRequest request, @PathVariable Integer examId,
            @RequestParam(required = false) Boolean upload, @RequestParam(required = false) Boolean absent) {
        User user = RequestUtils.getApiUser(request);
        Exam exam = examService.findById(examId);
        if (exam != null && exam.getSchoolId().equals(user.getSchoolId())) {
            ExamStudentSearchQuery query = new ExamStudentSearchQuery();
            query.setExamId(examId);
            query.setUpload(upload);
            query.setAbsent(absent);
            return examStudentService.countByQuery(query);
        }
        return 0;
    }

    @AuthValidate("adminUser")
    @RequestMapping("/exam/students")
    @ResponseBody
    public JSONArray getStudent(HttpServletRequest request, ExamStudentSearchQuery query,
            @RequestParam(required = false) Boolean withScoreDetail) {
        User user = RequestUtils.getApiUser(request);
        JSONArray array = new JSONArray();
        if (query.getExamId() == null) {
            return array;
        }
        Exam exam = examService.findById(query.getExamId());
        if (exam != null && exam.getSchoolId().equals(user.getSchoolId())) {
            DecimalFormat format = new DecimalFormat("####.##");
            examStudentService.findByQuery(query);
            for (ExamStudent student : query.getResult()) {
                JSONObject obj = new JSONObject();
                obj.accumulate("id", student.getId());
                obj.accumulate("schoolId", student.getSchoolId());
                obj.accumulate("examNumber", student.getExamNumber());
                obj.accumulate("campusName", student.getCampusName());
                obj.accumulate("subjectCode", student.getSubjectCode());
                obj.accumulate("subjectName", student.getSubjectName());
                obj.accumulate("name", student.getName());
                obj.accumulate("studentCode", student.getStudentCode());
                obj.accumulate("packageCode", student.getPackageCode());
                obj.accumulate("batchCode", student.getBatchCode() == null ? "" : student.getBatchCode());
                obj.accumulate("sheetCount", student.getSheetCount() != null ? student.getSheetCount() : 0);
                obj.accumulate("sliceCount", student.getSliceCount() != null ? student.getSliceCount() : 0);
                obj.accumulate("answers", StringUtils.trimToEmpty(student.getAnswers()));
                obj.accumulate("upload", student.isUpload());
                obj.accumulate("absent", student.isAbsent());
                obj.accumulate("manualAbsent", student.isManualAbsent());
                obj.accumulate("breach", student.isBreach());
                obj.accumulate("objectiveScore",
                        student.getObjectiveScore() == null ? "" : format.format(student.getObjectiveScore()));
                obj.accumulate("subjectiveScore",
                        student.getSubjectiveScore() == null ? "" : format.format(student.getSubjectiveScore()));
                Campus campus = campusService.findBySchoolAndName(student.getSchoolId(), student.getCampusName());
                obj.accumulate("campusCode", campus != null ? campus.getId().toString() : "");

                try {
                    if (withScoreDetail != null && withScoreDetail.booleanValue()) {
                        // 构造客观题得分明细
                        JSONArray objective = new JSONArray();
                        List<ScoreItem> scoreList = student.getScoreList(true);
                        List<ExamQuestion> questionList = questionService
                                .findByExamAndSubjectAndObjective(student.getExamId(), student.getSubjectCode(), true);
                        int i = 0;
                        for (ScoreItem item : scoreList) {
                            i++;
                            if (questionList.size() < i) {
                                break;
                            }
                            ExamQuestion question = questionList.get(i - 1);
                            if (question.getTotalScore() == null || question.getTotalScore() == 0) {
                                continue;
                            }
                            JSONObject detail = new JSONObject();
                            detail.accumulate("mainNumber", question.getMainNumber());
                            detail.accumulate("subNumber", question.getSubNumber());
                            detail.accumulate("score", item.getScore());
                            detail.accumulate("answer", item.getAnswer());
                            objective.add(detail);
                        }
                        obj.accumulate("objectiveScoreDetail", objective);

                        // 构造主观题得分明细
                        JSONArray subjective = new JSONArray();
                        scoreList = student.getScoreList(false);
                        questionList = questionService.findByExamAndSubjectAndObjective(student.getExamId(),
                                student.getSubjectCode(), false);
                        i = 0;
                        for (ScoreItem item : scoreList) {
                            i++;
                            if (questionList.size() < i) {
                                break;
                            }
                            ExamQuestion question = questionList.get(i - 1);
                            if (question.getTotalScore() == null || question.getTotalScore() == 0) {
                                continue;
                            }
                            JSONObject detail = new JSONObject();
                            detail.accumulate("mainNumber", question.getMainNumber());
                            detail.accumulate("subNumber", question.getSubNumber());
                            detail.accumulate("score", item.getScore());
                            subjective.add(detail);
                        }
                        obj.accumulate("subjectiveScoreDetail", subjective);
                    }
                    array.add(obj);
                } catch (Exception e) {
                    logger.error("student api error", e);
                }
            }
        }
        return array;
    }

    @AuthValidate("adminUser")
    @RequestMapping(value = "/student/check", method = RequestMethod.POST)
    @ResponseBody
    public JSONObject checkStudent(HttpServletRequest request, @RequestBody ExamStudent examStudent) {
        JSONObject obj = new JSONObject();
        Exam exam = examService.findById(examStudent.getExamId());
        ExamStudent student = examStudentService.findByExamIdAndExamNumber(examStudent.getExamId(),
                examStudent.getExamNumber());
        if (student != null) {
            obj.accumulate("examId", examStudent.getExamId());
            obj.accumulate("campusName", student.getCampusName());
            obj.accumulate("examNumber", student.getExamNumber());
            obj.accumulate("name", student.getName());
            obj.accumulate("studentId", String.valueOf(student.getId()));
            obj.accumulate("subjectCode", student.getSubjectCode());
            obj.accumulate("subjectName", student.getSubjectName());

            Campus campus = campusService.findBySchoolAndName(exam.getSchoolId(), student.getCampusName());
            obj.accumulate("campusCode", campus != null ? campus.getId().toString() : "");
        } else {
            obj.accumulate("examId", examStudent.getExamId());
            obj.accumulate("campusCode", "");
            obj.accumulate("campusName", "");
            obj.accumulate("examNumber", examStudent.getExamNumber());
            obj.accumulate("name", "");
            obj.accumulate("studentId", "");
            obj.accumulate("subjectCode", "");
            obj.accumulate("subjectName", "");
        }
        return obj;
    }

    /**
     * 
     * @param s
     *            需要转换的字符串
     * @param convert
     *            是否正向转换
     * @return
     */
    @SuppressWarnings("unused")
    private String convert(String s, String[] diploma, String[] bachelorDegree, boolean convert) {
        if (diploma == null || bachelorDegree == null) {
            return s;
        }

        char[] ss = s.toCharArray();
        String[] str = new String[ss.length];
        for (int i = 0; i < str.length; i++) {
            str[i] = String.valueOf(ss[i]);
        }

        if (convert) {
            if (str[Integer.parseInt(diploma[2]) - 1].equals(diploma[1])) {
                str[Integer.parseInt(diploma[2]) - 1] = diploma[0];
            }
            if (str[Integer.parseInt(diploma[3]) - 1].equals(diploma[1])) {
                str[Integer.parseInt(diploma[3]) - 1] = diploma[0];
            }
            if (str[Integer.parseInt(bachelorDegree[2]) - 1].equals(bachelorDegree[1])) {
                str[Integer.parseInt(bachelorDegree[2]) - 1] = bachelorDegree[0];
            }
            if (str[Integer.parseInt(bachelorDegree[3]) - 1].equals(bachelorDegree[1])) {
                str[Integer.parseInt(bachelorDegree[3]) - 1] = bachelorDegree[0];
            }
        } else {
            if (str[Integer.parseInt(diploma[2]) - 1].equals(diploma[0])) {
                str[Integer.parseInt(diploma[2]) - 1] = diploma[1];
            }
            if (str[Integer.parseInt(diploma[3]) - 1].equals(diploma[0])) {
                str[Integer.parseInt(diploma[3]) - 1] = diploma[1];
            }
            if (str[Integer.parseInt(bachelorDegree[2]) - 1].equals(bachelorDegree[0])) {
                str[Integer.parseInt(bachelorDegree[2]) - 1] = bachelorDegree[1];
            }
            if (str[Integer.parseInt(bachelorDegree[3]) - 1].equals(bachelorDegree[0])) {
                str[Integer.parseInt(bachelorDegree[3]) - 1] = bachelorDegree[1];
            }
        }
        StringBuffer sb = new StringBuffer();
        for (String i : str) {
            sb.append(i);
        }
        return sb.toString();
    }

    @RequestMapping(value = "/score/school/{schoolId}")
    @ResponseBody
    public String getScore(@PathVariable Integer schoolId, @RequestParam String studentCode,
            @RequestParam String subjectCode, @RequestParam(required = false, defaultValue = "true") boolean encrypt,
            @RequestParam(required = false) String examSeqCode, @RequestParam(required = false) Integer examId,
            @RequestParam(required = false, defaultValue = "false") boolean detail) {
        JSONObject obj = new JSONObject();
        ExamStudent student = null;
        try {
            if (StringUtils.isNotBlank(examSeqCode)) {
                student = examStudentService.findBySchoolIdAndSubjectCodeAndStudentCodeAndRemark(schoolId, subjectCode,
                        studentCode, examSeqCode);
            } else if (examId != null) {
                student = examStudentService.findByExamIdAndSchoolIdAndSubjectCodeAndStudentCode(examId, schoolId,
                        subjectCode, studentCode);
            } else {
                student = examStudentService.findBySchoolIdAndSubjectCodeAndStudentCode(schoolId, subjectCode,
                        studentCode);
            }
            if (student != null) {
                DecimalFormat df = new DecimalFormat("###.#");
                obj.accumulate("exist", true);
                obj.accumulate("examId", String.valueOf(student.getExamId()));
                obj.accumulate("upload", student.isUpload() && !student.isAbsent());
                if (student.isUpload() && !student.isAbsent()) {// 缺考
                    ExamSubject examSubject = examSubjectService.find(student.getExamId(), student.getSubjectCode());
                    int objectiveStatus = getObjectiveStatus(examSubject, student);
                    obj.accumulate("objectiveStatus", objectiveStatus);
                    int subjectiveStatus = getSubjectiveStatus(examSubject, student);
                    obj.accumulate("subjectiveStatus", subjectiveStatus);
                    double objectiveScore = objectiveStatus == 2 ? student.getObjectiveScore() : 0;
                    obj.accumulate("objectiveScore", df.format(objectiveScore));
                    double subjectiveScore = subjectiveStatus == 2 ? student.getSubjectiveScore() : 0;
                    obj.accumulate("subjectiveScore", df.format(subjectiveScore));
                    obj.accumulate("totalScore", df.format(objectiveScore + subjectiveScore));
                    if (detail) {
                        obj.accumulate("subjectiveScoreList",
                                subjectiveStatus == 2 ? StringUtils.trimToEmpty(student.getSubjectiveScoreList()) : "");
                    }
                } else {
                    absentSetObj(detail, obj);
                }
                obj.accumulate("absent", student.isAbsent());
            } else {
                obj.accumulate("exist", false);
                obj.accumulate("examId", "");
                obj.accumulate("upload", false);
                obj.accumulate("absent", true);
                absentSetObj(detail, obj);
            }
            if (StringUtils.isNotBlank(examSeqCode)) {
                obj.accumulate("examSeqCode", examSeqCode);
            }
            obj.accumulate("studentCode", studentCode);
            obj.accumulate("subjectCode", subjectCode);
        } catch (Exception e) {
            e.printStackTrace();
            obj.accumulate("exception", "500");
        }
        String result = obj.toString();
        return encrypt ? AESUtil.encrypt(result) : result;
    }

    private void absentSetObj(boolean detail, JSONObject obj) {
        obj.accumulate("objectiveStatus", "");
        obj.accumulate("subjectiveStatus", "");
        obj.accumulate("objectiveScore", "");
        obj.accumulate("subjectiveScore", "");
        obj.accumulate("totalScore", "");
        if (detail) {
            obj.accumulate("subjectiveScoreList", "");
        }
    }

    @RequestMapping(value = "/score/school/{schoolId}/all")
    @ResponseBody
    public String getAllScore(@PathVariable Integer schoolId,
            @RequestParam(required = false, defaultValue = "true") boolean encrypt,
            @RequestParam(required = false, defaultValue = "false") Integer examId,
            @RequestParam(required = false, defaultValue = "false") boolean detail) {
        JSONArray array = new JSONArray();
        List<ExamStudent> esList = new LinkedList<ExamStudent>();
        if (examId != null) {
            esList = examStudentService.findByExamId(examId);
        } else {
            List<Exam> exams = examService.findBySchoolId(schoolId);
            if (!exams.isEmpty()) {
                esList = examStudentService.findByExamId(exams.get(0).getId());
            }
        }
        for (ExamStudent student : esList) {
            JSONObject obj = new JSONObject();
            try {
                DecimalFormat df = new DecimalFormat("###.#");
                obj.accumulate("exist", true);
                obj.accumulate("examId", String.valueOf(student.getExamId()));
                obj.accumulate("upload", student.isUpload() && !student.isAbsent());
                if (student.isUpload() && !student.isAbsent()) {
                    ExamSubject examSubject = examSubjectService.find(student.getExamId(), student.getSubjectCode());
                    int objectiveStatus = getObjectiveStatus(examSubject, student);
                    obj.accumulate("objectiveStatus", objectiveStatus);
                    int subjectiveStatus = getSubjectiveStatus(examSubject, student);
                    obj.accumulate("subjectiveStatus", subjectiveStatus);
                    double objectiveScore = objectiveStatus == 2 ? student.getObjectiveScore() : 0;
                    obj.accumulate("objectiveScore", df.format(objectiveScore));
                    double subjectiveScore = subjectiveStatus == 2 ? student.getSubjectiveScore() : 0;
                    obj.accumulate("subjectiveScore", df.format(subjectiveScore));
                    obj.accumulate("totalScore", df.format(objectiveScore + subjectiveScore));
                    if (detail) {
                        obj.accumulate("subjectiveScoreList",
                                subjectiveStatus == 2 ? StringUtils.trimToEmpty(student.getSubjectiveScoreList()) : "");
                    }
                } else {
                    absentSetObj(detail, obj);
                }
                obj.accumulate("studentCode", student.getStudentCode());
                obj.accumulate("subjectCode", student.getSubjectCode());
            } catch (Exception e) {
                e.printStackTrace();
                obj.accumulate("exception", "500");
            }
            array.add(obj);
        }
        String result = array.toString();
        return encrypt ? AESUtil.encrypt(result) : result;
    }

    @RequestMapping(value = "/score/school/{schoolId}/hk")
    @ResponseBody
    public String getHKScore(@PathVariable Integer schoolId, @RequestParam String studentCode,
            @RequestParam String subjectCode, @RequestParam(required = false, defaultValue = "true") boolean encrypt,
            @RequestParam(required = false) String examSeqCode, @RequestParam(required = false) Integer examId,
            @RequestParam(required = false, defaultValue = "false") boolean detail) {
        JSONObject obj = new JSONObject();
        ExamStudent student = null;
        try {
            if (StringUtils.isNotBlank(examSeqCode)) {
                student = examStudentService.findBySchoolIdAndSubjectCodeAndStudentCodeAndRemark(schoolId, subjectCode,
                        studentCode, examSeqCode);
            } else if (examId != null) {
                student = examStudentService.findByExamIdAndSchoolIdAndSubjectCodeAndStudentCode(examId, schoolId,
                        subjectCode, studentCode);
            } else {
                student = examStudentService.findBySchoolIdAndSubjectCodeStartingWithAndStudentCode(schoolId,
                        subjectCode, studentCode);
            }
            if (student != null) {
                DecimalFormat df = new DecimalFormat("###.#");
                obj.accumulate("exist", true);
                obj.accumulate("examId", String.valueOf(student.getExamId()));
                obj.accumulate("upload", student.isUpload() && !student.isAbsent());
                if (student.isUpload() && !student.isAbsent()) {// 缺考
                    ExamSubject examSubject = examSubjectService.find(student.getExamId(), student.getSubjectCode());
                    int objectiveStatus = getObjectiveStatus(examSubject, student);
                    obj.accumulate("objectiveStatus", objectiveStatus);
                    int subjectiveStatus = getSubjectiveStatus(examSubject, student);
                    obj.accumulate("subjectiveStatus", subjectiveStatus);
                    double objectiveScore = objectiveStatus == 2 ? student.getObjectiveScore() : 0;
                    obj.accumulate("objectiveScore", df.format(objectiveScore));
                    obj.accumulate("subjectiveScore", df.format(student.getSubjectiveScore()));
                    obj.accumulate("totalScore", df.format(objectiveScore + student.getSubjectiveScore()));
                    if (detail) {
                        obj.accumulate("subjectiveScoreList",
                                subjectiveStatus == 2 ? StringUtils.trimToEmpty(student.getSubjectiveScoreList()) : "");
                    }
                } else {
                    absentSetObj(detail, obj);
                }
            } else {
                obj.accumulate("exist", false);
                obj.accumulate("examId", "");
                obj.accumulate("upload", false);
                absentSetObj(detail, obj);
            }
            if (StringUtils.isNotBlank(examSeqCode)) {
                obj.accumulate("examSeqCode", examSeqCode);
            }
            obj.accumulate("studentCode", studentCode);
            obj.accumulate("subjectCode", subjectCode);
        } catch (Exception e) {
            e.printStackTrace();
            obj.accumulate("exception", "500");
        }
        String result = obj.toString();
        return encrypt ? AESUtil.encrypt(result) : result;
    }

    private int getSubjectiveStatus(ExamSubject examSubject, ExamStudent student) {
        if (examSubject.getSubjectiveScore() == null || examSubject.getSubjectiveScore() == 0) {
            return 0;
        } else {
            MarkLibrary markLibrary = markLibraryService.findByStudentId(student.getId());
            if (StringUtils.isNotEmpty(markLibrary.getMarkerScoreList())
                    && markLibrary.getStatus().equals(LibraryStatus.MARKED)) {
                return 2;
            } else {
                return 1;
            }
        }
    }

    private int getObjectiveStatus(ExamSubject examSubject, ExamStudent student) {
        if (examSubject.getObjectiveScore() == null || examSubject.getObjectiveScore() == 0) {
            return 0;
        } else {
            if (StringUtils.isEmpty(student.getObjectiveScoreList())) {
                return 1;
            } else {
                return 2;
            }
        }
    }

    /**
     * 上传考生个人试卷结构接口
     * 
     * @param request
     * @param examId
     * @param examNumber
     * @param objective
     * @param struct
     * @return
     */
    @AuthValidate("adminUser")
    @RequestMapping(value = "/student/struct", method = RequestMethod.POST)
    @ResponseBody
    private boolean uploadStruct(HttpServletRequest request, @RequestParam Integer examId,
            @RequestParam String examNumber, @RequestParam Boolean objective, @RequestParam String struct) {
        // 验证考试与管理员账号
        User user = RequestUtils.getApiUser(request);
        Exam exam = examService.findById(examId);
        if (exam == null || !exam.getSchoolId().equals(user.getSchoolId())) {
            throw ApiException.EXAM_NOT_ACCESSIBLED;
        }
        // 验证考生是否存在
        ExamStudent student = examStudentService.findByExamIdAndExamNumber(examId, examNumber);
        if (student == null) {
            return false;
        }
        // 尝试解析试卷结构
        struct = StringUtils.trimToEmpty(struct);
        List<QuestionDetail> list = ExamStudentPaper.parseFromJson(struct);
        if (list == null || list.isEmpty()) {
            return false;
        }
        // 保存个人试卷结构
        ExamStudentPaper paper = studentPaperService.find(examId, examNumber, objective);
        if (paper == null) {
            paper = new ExamStudentPaper();
            paper.setExamId(examId);
            paper.setExamNumber(examNumber);
            paper.setObjective(objective);
        }
        paper.setStruct(struct);
        studentPaperService.save(paper);
        // 同步科目总分信息
        ExamSubject subject = examSubjectService.find(examId, student.getSubjectCode());
        if (objective.booleanValue() && subject.getObjectiveScore() == null) {
            subject.setObjectiveScore(sumTotalScore(list));
            examSubjectService.save(subject);
        } else if (!objective.booleanValue() && subject.getSubjectiveScore() == null) {
            subject.setSubjectiveScore(sumTotalScore(list));
            examSubjectService.save(subject);
        }
        return true;
    }

    /**
     * 计算个人试卷结构中的总分
     * 
     * @param list
     * @return
     */
    private double sumTotalScore(List<QuestionDetail> list) {
        double score = 0d;
        for (QuestionDetail detail : list) {
            if (detail.getQuestions() == null) {
                continue;
            }
            for (QuestionUnit unit : detail.getQuestions()) {
                score += unit.getScore();
            }
        }
        return score;
    }
}
