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

import java.io.File;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import cn.com.qmth.stmms.admin.utils.UpyunConfig;
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.ExamStudent;
import cn.com.qmth.stmms.biz.exam.service.ExamService;
import cn.com.qmth.stmms.biz.exam.service.ExamStudentService;
import cn.com.qmth.stmms.common.enums.ExamStatus;
import cn.com.qmth.stmms.common.upyun.UpYun;
import cn.com.qmth.stmms.common.utils.PictureUrlBuilder;

public class ImageCheckThread implements Runnable {

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

    private int examId;

    private UpYun sheetUpyun;

    private UpYun sliceUpyun;

    private String baseDir;

    private ExamService examService;

    private ExamStudentService studentService;

    private CampusService campusService;

    public ImageCheckThread(int examId, UpyunConfig config, String baseDir, ExamService examService,
            ExamStudentService studentService, CampusService campusService) {
        this.examId = examId;
        this.sheetUpyun = new UpYun(config.getSheetBucket(), config.getSheetUsername(), config.getSheetPassword());
        this.sliceUpyun = new UpYun(config.getSliceBucket(), config.getSliceUsername(), config.getSlicePassword());
        this.baseDir = baseDir;
        this.examService = examService;
        this.studentService = studentService;
        this.campusService = campusService;
    }

    @Override
    public void run() {
        log.info("start check image for examId=" + examId);
        try {
            int pageNumber = 1;
            int pageSize = 500;
            while (true) {
                List<ExamStudent> list = studentService.findByExamIdAndUploadAndAbsent(examId, true, false, pageNumber,
                        pageSize);
                if (list == null || list.isEmpty()) {
                    break;
                }

                for (ExamStudent student : list) {
                    checkStudent(student);
                }

                pageNumber++;
            }
        } catch (Exception e) {
            log.error("check image exception for examId=" + examId, e);
        } finally {
            examService.updateStatus(examId, ExamStatus.START);
            log.info("finish check image for examId=" + examId);
        }
    }

    private void checkStudent(ExamStudent student) {
        Campus campus = campusService.findBySchoolAndName(student.getSchoolId(), student.getCampusName());
        if (student.getSheetCount() == 0 || student.getSliceCount() == 0 || campus == null) {
            record(student, true);
            return;
        }

        List<String> sheetUrls = PictureUrlBuilder.getSheetUrls(examId, campus.getId(), student.getSubjectCode(),
                student.getExamNumber(), student.getSheetCount());
        for (String url : sheetUrls) {
            if (!exist(url, sheetUpyun)) {
                record(student, true);
                return;
            }
        }

        List<String> sliceUrls = PictureUrlBuilder.getSliceUrls(examId, campus.getId(), student.getSubjectCode(),
                student.getExamNumber(), 1, student.getSliceCount());
        for (String url : sliceUrls) {
            if (!exist(url, sliceUpyun)) {
                record(student, true);
                return;
            }
        }

        record(student, false);
    }

    private void record(ExamStudent student, boolean exception) {
        studentService.updateException(student.getId(), exception);
    }

    private boolean exist(String path, UpYun config) {
        if (StringUtils.isNotBlank(baseDir)) {
            try {
                File file = new File(baseDir, config.getBucketName() + path);
                return file.exists() && file.isFile();
            } catch (Exception e) {
                return false;
            }
        } else {
            int retry = 1;
            while (retry <= 3) {
                try {
                    Map<String, String> result = config.getFileInfo(path);
                    return result != null && "file".equals(result.get("type"));
                } catch (Exception e) {
                    retry++;
                    continue;
                }
            }
            return false;
        }
    }
}
