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

import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.List;

import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang.StringUtils;
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.core.task.AsyncTaskExecutor;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import cn.com.qmth.stmms.admin.utils.UpyunConfig;
import cn.com.qmth.stmms.api.utils.ImageBuildUtil;
import cn.com.qmth.stmms.api.utils.SheetDownloadThread;
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.service.ExamService;
import cn.com.qmth.stmms.biz.exam.service.ExamStudentService;
import cn.com.qmth.stmms.biz.lock.LockService;
import cn.com.qmth.stmms.biz.utils.PictureTag;
import cn.com.qmth.stmms.common.enums.LockType;
import cn.com.qmth.stmms.common.upyun.UpYun;
import cn.com.qmth.stmms.common.utils.PictureUrlBuilder;
import net.sf.json.JSONObject;

@Controller("pictureController")
@RequestMapping("/")
public class PictureController {

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

    @Autowired
    private ExamService examService;

    @Autowired
    private CampusService campusService;

    @Autowired
    private ExamStudentService studentService;

    @Autowired
    private UpyunConfig config;

    @Autowired
    private LockService lockService;

    @Autowired
    private AsyncTaskExecutor taskExecutor;

    @Value("${sheet.image.server}")
    private String sheetServer;

    @Value("${file.root}")
    private String baseDir;

    @Value("${file.save}")
    private String saveDir;

    @RequestMapping("/sheet/{examId}/{examNumber}-{index}")
    public void getSheet(HttpServletResponse response, @PathVariable Integer examId, @PathVariable String examNumber,
            @PathVariable Integer index, @RequestParam(required = false, defaultValue = "true") Boolean withTag)
            throws IOException {
        ExamStudent student = studentService.findByExamIdAndExamNumber(examId, examNumber);
        if (student == null || !student.isUpload() || index < 1 || index > student.getSheetCount()) {
            response.sendError(HttpStatus.NOT_FOUND.value());
            return;
        }
        try {
            List<PictureTag> tags = null;
            if (withTag != null && withTag) {
                tags = studentService.buildSheetTags(student, index);
            }
            BufferedImage image = ImageBuildUtil.buildTagImage(getSheetImage(student, index), tags);
            response.setContentType("image/jpeg");
            ImageIO.write(image, "jpg", response.getOutputStream());
        } catch (Exception e) {
            log.error("get sheet error", e);
            response.reset();
            response.sendError(HttpStatus.NOT_FOUND.value());
            return;
        }
    }

    @RequestMapping("/sheet/{examId}/save")
    @ResponseBody
    public Object saveAllSheet(HttpServletResponse response, @PathVariable Integer examId,
            @RequestParam(required = false, defaultValue = "true") Boolean withTag) throws IOException {
        JSONObject result = new JSONObject();
        Exam exam = examService.findById(examId);
        if (exam == null) {
            result.accumulate("success", false);
            result.accumulate("message", "exam not exists");
            return result;
        }
        if (StringUtils.isBlank(saveDir)) {
            result.accumulate("success", false);
            result.accumulate("message", "file.save not exists");
            return result;
        }
        if (!lockService.isLocked(LockType.SAVE_SHEET, examId)) {
            taskExecutor.submit(new SheetDownloadThread(examId, saveDir, withTag, this, studentService, lockService));
        }
        result.accumulate("running", lockService.isLocked(LockType.SAVE_SHEET, examId));
        return result;
    }

    @RequestMapping("/sheet/{examId}/status")
    @ResponseBody
    public Object saveAllSheetStatus(HttpServletResponse response, @PathVariable Integer examId) throws IOException {
        JSONObject result = new JSONObject();
        result.accumulate("running", lockService.isLocked(LockType.SAVE_SHEET, examId));
        return result;
    }

    public BufferedImage getSheetImage(ExamStudent student, int index) throws FileNotFoundException, IOException {
        Campus campus = campusService.findBySchoolAndName(student.getSchoolId(), student.getCampusName());
        String url = PictureUrlBuilder.getSheetUrl(student.getExamId(), campus.getId(), student.getSubjectCode(),
                student.getExamNumber(), index);
        if (StringUtils.isNotBlank(baseDir)) {
            return ImageIO.read(new File(new File(baseDir, config.getSheetBucket()), url));
        } else {
            UpYun upyun = new UpYun(config.getSheetBucket(), config.getSheetUsername(), config.getSheetPassword());
            ByteArrayOutputStream ous = new ByteArrayOutputStream();
            upyun.readFile(url, ous);
            return ImageIO.read(new ByteArrayInputStream(ous.toByteArray()));
        }
    }

    public BufferedImage getSliceImage(ExamStudent student, int index) throws FileNotFoundException, IOException {
        Campus campus = campusService.findBySchoolAndName(student.getSchoolId(), student.getCampusName());
        String url = PictureUrlBuilder.getSliceUrl(student.getExamId(), campus.getId(), student.getSubjectCode(),
                student.getExamNumber(), index);
        if (StringUtils.isNotBlank(baseDir)) {
            return ImageIO.read(new File(new File(baseDir, config.getSliceBucket()), url));
        } else {
            UpYun upyun = new UpYun(config.getSliceBucket(), config.getSliceUsername(), config.getSlicePassword());
            ByteArrayOutputStream ous = new ByteArrayOutputStream();
            upyun.readFile(url, ous);
            return ImageIO.read(new ByteArrayInputStream(ous.toByteArray()));
        }
    }

}
