package cn.com.qmth.stmms.biz.mark.service.Impl;

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

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.domain.Sort;
import org.springframework.data.domain.Sort.Direction;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

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.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.query.ExamSearchQuery;
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.impl.MemoryLockProvider;
import cn.com.qmth.stmms.biz.mark.service.MarkService;
import cn.com.qmth.stmms.biz.utils.CurrentTaskUtil;
import cn.com.qmth.stmms.common.enums.ExamStatus;

/**
 * 与评卷相关的所有定时任务
 * 
 * @author luoshi
 *
 */
@Component
public class MarkCronService {

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

    @Autowired
    private ExamService examService;

    @Autowired
    private CampusService campusService;

    @Autowired
    private ExamStudentService studentService;

    @Autowired
    private ExamSubjectService subjectService;

    @Autowired
    private MarkGroupService groupService;

    @Autowired
    private MarkService markService;

    @Autowired
    private MarkLockService lockService;

    @Autowired
    private MemoryLockProvider memoryLock;

    @Value("${mark.cleanTimeoutMinute}")
    private long timeoutMinute;

    /**
     * 自动释放可清除的锁
     */
    @Scheduled(cron = "${mark.cleanLockSchedule}")
    public void cronCleanLock() {
        try {
            lockService.clear();
            memoryLock.clear();
        } catch (Exception e) {
            log.error("CronCleanTask error", e);
        }
    }

    /**
     * 自动释放超时未处理的评卷任务
     */
    @Scheduled(cron = "${mark.cleanTaskSchedule}")
    public void cronCleanTask() {
        try {
            CurrentTaskUtil.clearTimeoutTask(timeoutMinute);
        } catch (Exception e) {
            log.error("CronCleanTask error", e);
        }
    }

    /**
     * 定时生成评卷任务
     */
    @Scheduled(fixedDelay = 2 * 60 * 1000, initialDelay = 60 * 1000)
    public void buildLibrary() {
        log.debug("start auto-create library");
        try {
            Map<String, Campus> campusMap = new HashMap<String, Campus>();

            ExamSearchQuery query = new ExamSearchQuery();
            query.addStatus(ExamStatus.START);
            query.setSort(new Sort(Direction.DESC, "id"));
            query.setPageNumber(1);
            query.setPageSize(10);
            query = examService.findByQuery(query);
            while (query.getCurrentCount() > 0) {
                for (Exam exam : query.getResult()) {
                    buildLibraryByExam(exam, campusMap);
                }
                query.setPageNumber(query.getPageNumber() + 1);
                query = examService.findByQuery(query);
            }
        } catch (Exception e) {
            log.error("auto-create library error", e);
        } finally {
            log.debug("finish auto-create library");
        }
    }

    private void buildLibraryByExam(Exam exam, Map<String, Campus> campusMap) {
        // 获取主观题总分大于0的科目
        List<ExamSubject> subjects = subjectService.list(exam.getId(), 0);
        for (ExamSubject subject : subjects) {
            // 清除缺考考生和违纪考生
            List<ExamStudent> list = studentService.findAbsentOrBreachLibraryStudent(subject.getExamId(),
                    subject.getCode());
            if (list != null) {
                for (ExamStudent student : list) {
                    markService.deleteByStudent(student);
                }
            }
            // 处理正常考生
            List<MarkGroup> groups = groupService.findByExamAndSubject(subject.getExamId(), subject.getCode());
            for (MarkGroup group : groups) {
                Date lastBuildTime = group.getBuildTime();
                ExamStudent student = studentService.findUnLibraryStudent(exam.getId(), subject.getCode(),
                        group.getNumber(), lastBuildTime);
                while (student != null) {
                    // 补充学习中心集合
                    Campus campus = campusMap.get(student.getSchoolId() + "_" + student.getCampusName());
                    if (campus == null) {
                        campus = campusService.findBySchoolAndName(student.getSchoolId(), student.getCampusName());
                        if (campus == null) {
                            log.error("campus unexist for student id=" + student.getId());
                            continue;
                        } else {
                            campusMap.put(student.getSchoolId() + "_" + student.getCampusName(), campus);
                        }
                    }
                    // 尝试构造评卷任务
                    try {
                        markService.buildLibrary(student, campus, group);
                        lastBuildTime = student.getUploadTime();
                    } catch (Exception e) {
                        log.error("build library error for studentId=" + student.getId() + ", groupNumber="
                                + group.getNumber(), e);
                    }
                    // 取下一个考生
                    student = studentService.findUnLibraryStudent(exam.getId(), subject.getCode(), group.getNumber(),
                            lastBuildTime);
                }
            }
        }
    }
}
