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

import cn.com.qmth.stmms.biz.exam.model.ExamStudent;
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.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.file.enums.FileType;
import cn.com.qmth.stmms.biz.file.enums.FormatType;
import cn.com.qmth.stmms.biz.user.model.User;
import cn.com.qmth.stmms.biz.user.service.UserService;
import cn.com.qmth.stmms.biz.utils.ScoreCalculateUtil;
import cn.com.qmth.stmms.biz.utils.ScoreInfo;
import cn.com.qmth.stmms.common.enums.*;
import cn.com.qmth.stmms.common.utils.DateUtils;
import org.apache.commons.lang3.StringEscapeUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.propertyeditors.CustomBooleanEditor;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.InitBinder;

import java.beans.PropertyEditorSupport;
import java.util.Date;
import java.util.List;

public class BaseController {

    @Autowired
    private UserService userService;

    @Autowired
    private ExamStudentService studentService;

    @Autowired
    private ExamSubjectService subjectService;

    @Autowired
    private ExamQuestionService questionService;

    @Autowired
    private MarkGroupService groupService;

    protected boolean checkLoginName(User user) {
        User previous = userService.findByLoginName(user.getLoginName());
        if (previous == null || (user.getId() != null && previous.getId().equals(user.getId()))) {
            return true;
        } else {
            return false;
        }
    }

    /**
     * 初始化数据绑定 1. 将所有传递进来的String进行HTML编码，防止XSS攻击 2. 将字段中Date类型转换为String类型
     */
    @InitBinder
    protected void initBinder(WebDataBinder binder) {
        // String类型转换，将所有传递进来的String进行HTML编码，防止XSS攻击
        binder.registerCustomEditor(String.class, new PropertyEditorSupport() {

            @Override
            public void setAsText(String text) {
                setValue(text == null ? null : StringEscapeUtils.escapeHtml4(text.trim()));
            }

            @Override
            public String getAsText() {
                Object value = getValue();
                return value != null ? value.toString() : "";
            }
        });
        // Date 类型转换
        binder.registerCustomEditor(Date.class, new PropertyEditorSupport() {

            @Override
            public void setAsText(String text) {
                setValue(DateUtils.parseDate(text));
            }
        });
        // ExamSubjectStatus 类型转换
        binder.registerCustomEditor(ExamSubjectStatus.class, new PropertyEditorSupport() {

            @Override
            public void setAsText(String text) {
                try {
                    setValue(ExamSubjectStatus.findByValue(Integer.valueOf(text)));
                } catch (Exception e) {
                    setValue(null);
                }
            }
        });
        // LibraryStatus 类型转换
        binder.registerCustomEditor(LibraryStatus.class, new PropertyEditorSupport() {

            @Override
            public void setAsText(String text) {
                try {
                    setValue(LibraryStatus.findByValue(Integer.valueOf(text)));
                } catch (Exception e) {
                    setValue(null);
                }
            }
        });
        // Role 类型转换
        binder.registerCustomEditor(Role.class, new PropertyEditorSupport() {

            @Override
            public void setAsText(String text) {
                try {
                    setValue(Role.findByValue(Integer.valueOf(text)));
                } catch (Exception e) {
                    setValue(null);
                }
            }
        });
        // UserSource 类型转换
        binder.registerCustomEditor(UserSource.class, new PropertyEditorSupport() {

            @Override
            public void setAsText(String text) {
                try {
                    setValue(UserSource.findByValue(Integer.valueOf(text)));
                } catch (Exception e) {
                    setValue(null);
                }
            }
        });
        // MarkStatus 类型转换
        binder.registerCustomEditor(MarkStatus.class, new PropertyEditorSupport() {

            @Override
            public void setAsText(String text) {
                try {
                    setValue(MarkStatus.findByName(text));
                } catch (Exception e) {
                    setValue(null);
                }
            }
        });
        // MarkMode 类型转换
        binder.registerCustomEditor(MarkMode.class, new PropertyEditorSupport() {

            @Override
            public void setAsText(String text) {
                try {
                    setValue(MarkMode.findByName(text));
                } catch (Exception e) {
                    setValue(null);
                }
            }
        });

        // HistoryStatus 类型转换
        binder.registerCustomEditor(HistoryStatus.class, new PropertyEditorSupport() {

            @Override
            public void setAsText(String text) {
                try {
                    setValue(HistoryStatus.findByValue(Integer.valueOf(text)));
                } catch (Exception e) {
                    setValue(null);
                }
            }
        });

        // CheckType 类型转换
        binder.registerCustomEditor(CheckType.class, new PropertyEditorSupport() {

            @Override
            public void setAsText(String text) {
                try {
                    setValue(CheckType.findByValue(Integer.valueOf(text)));
                } catch (Exception e) {
                    setValue(null);
                }
            }
        });
        // ObjectivePolicy 类型转换
        binder.registerCustomEditor(ObjectivePolicy.class, new PropertyEditorSupport() {

            @Override
            public void setAsText(String text) {
                try {
                    setValue(ObjectivePolicy.findByValue(Integer.valueOf(text)));
                } catch (Exception e) {
                    setValue(null);
                }
            }
        });
        // ExamStatus 类型转换
        binder.registerCustomEditor(ExamStatus.class, new PropertyEditorSupport() {

            @Override
            public void setAsText(String text) {
                try {
                    setValue(ExamStatus.findByValue(Integer.valueOf(text)));
                } catch (Exception e) {
                    setValue(null);
                }
            }
        });
        // ExamType 类型转换
        binder.registerCustomEditor(ExamType.class, new PropertyEditorSupport() {

            @Override
            public void setAsText(String text) {
                try {
                    setValue(ExamType.findByValue(Integer.valueOf(text)));
                } catch (Exception e) {
                    setValue(null);
                }
            }
        });
        // LogType 类型转换
        binder.registerCustomEditor(LogType.class, new PropertyEditorSupport() {

            @Override
            public void setAsText(String text) {
                try {
                    setValue(LogType.findByValue(Integer.valueOf(text)));
                } catch (Exception e) {
                    setValue(null);
                }
            }
        });
        // FileType 类型转换
        binder.registerCustomEditor(FileType.class, new PropertyEditorSupport() {

            @Override
            public void setAsText(String text) {
                try {
                    setValue(FileType.findByText(text));
                } catch (Exception e) {
                    setValue(null);
                }
            }
        });
        // FormatType 类型转换
        binder.registerCustomEditor(FormatType.class, new PropertyEditorSupport() {

            @Override
            public void setAsText(String text) {
                try {
                    setValue(FormatType.findByText(text));
                } catch (Exception e) {
                    setValue(null);
                }
            }
        });
        // ExamSource 类型转换
        binder.registerCustomEditor(ExamSource.class, new PropertyEditorSupport() {

            @Override
            public void setAsText(String text) {
                try {
                    setValue(ExamSource.findByValue(Integer.valueOf(text)));
                } catch (Exception e) {
                    setValue(null);
                }
            }
        });
        // SubjectiveStatus 类型转换
        binder.registerCustomEditor(SubjectiveStatus.class, new PropertyEditorSupport() {

            @Override
            public void setAsText(String text) {
                try {
                    setValue(SubjectiveStatus.findByText(text));
                } catch (Exception e) {
                    setValue(null);
                }
            }
        });
        // SelectiveStatus 类型转换
        binder.registerCustomEditor(SelectiveStatus.class, new PropertyEditorSupport() {

            @Override
            public void setAsText(String text) {
                try {
                    setValue(SelectiveStatus.findByValue(Integer.valueOf(text)));
                } catch (Exception e) {
                    setValue(null);
                }
            }
        });
        // SystemAuthType 类型转换
        binder.registerCustomEditor(SystemAuthType.class, new PropertyEditorSupport() {

            @Override
            public void setAsText(String text) {
                try {
                    setValue(SystemAuthType.findByValue(Integer.valueOf(text)));
                } catch (Exception e) {
                    setValue(null);
                }
            }
        });
        // QuestionType 类型转换
        binder.registerCustomEditor(QuestionType.class, new PropertyEditorSupport() {

            @Override
            public void setAsText(String text) {
                try {
                    setValue(QuestionType.findByValue(Integer.valueOf(text)));
                } catch (Exception e) {
                    setValue(null);
                }
            }
        });
        binder.registerCustomEditor(Boolean.class, new CustomBooleanEditor(true));
    }

    protected boolean saveUploadStudent(ExamStudent student) {
        ExamStudent old = studentService.findById(student.getId());
        if (!student.isAbsent()) {// 正考
            List<MarkGroup> groupList = groupService.findByExamAndSubjectAndStatus(student.getExamId(),
                    student.getSubjectCode(), MarkStatus.FINISH);
            for (MarkGroup markGroup : groupList) {
                groupService.updateStatus(student.getExamId(), student.getSubjectCode(), markGroup.getNumber(),
                        MarkStatus.FORMAL, MarkStatus.FINISH);
            }
        }
        calculateObjectiveScore(student);
        if (student.isAbsent()) {// 转缺考
            student.setObjectiveScore(0d);
            student.setObjectiveScoreList(null);
        }
        if (!old.isAbsent() && student.isAbsent()) {// 正考转缺考
            student.setSubjectiveScore(0d);
            student.setSubjectiveScoreList(null);
            student.setInspectCount(0);
            studentService.save(student);
            studentService.updateSubjectiveStatusAndScore(student.getId(), SubjectiveStatus.UNMARK, 0, null);
        }
        boolean success = studentService.updateScanInfo(student);
        if (success) {
            subjectService.updateUploadCount(
                    student.getExamId(),
                    student.getSubjectCode(),
                    (int) studentService.countUploadedByExamIdAndSubjectCode(student.getExamId(),
                            student.getSubjectCode()));
        }
        return success;
    }

    private void calculateObjectiveScore(ExamStudent student) {
        ScoreCalculateUtil util = ScoreCalculateUtil.instance(student);

        ScoreInfo info = util.calculate(
                questionService.findByExamAndSubjectAndObjectiveAndPaperType(student.getExamId(),
                        student.getSubjectCode(), true, student.getPaperType()), null);

        student.setObjectiveScore(info.getObjectiveScore());
        student.setScoreList(info.getScoreList(), true);
    }
}
