package cn.com.qmth.stmms.ms.collect.util;

import cn.com.qmth.stmms.ms.commons.config.AliYunOssConfig;
import cn.com.qmth.stmms.ms.commons.config.ImageConfig;
import cn.com.qmth.stmms.ms.commons.config.ImageServerConfig;
import cn.com.qmth.stmms.ms.commons.config.SystemConfig;
import cn.com.qmth.stmms.ms.commons.constant.SystemConstant;
import cn.com.qmth.stmms.ms.commons.utils.MD5Util;
import cn.com.qmth.stmms.ms.commons.utils.OssUtil;
import cn.com.qmth.stmms.ms.commons.utils.image.ImageCompression;
import cn.com.qmth.stmms.ms.core.cache.ParamCache;
import cn.com.qmth.stmms.ms.core.domain.Paper;
import cn.com.qmth.stmms.ms.core.domain.Student;
import cn.com.qmth.stmms.ms.core.repository.PaperRepo;
import cn.com.qmth.stmms.ms.core.repository.StudentRepo;
import org.apache.commons.codec.digest.DigestUtils;
import org.slf4j.LoggerFactory;
import org.springframework.util.FileCopyUtils;

import java.io.*;
import java.util.HashSet;
import java.util.StringJoiner;

public class RotateTask implements Runnable {
    private static final org.slf4j.Logger LOGGER = LoggerFactory.getLogger(RotateTask.class);
    ImageConfig imageConfig;
    StudentRepo studentRepo;
    private Paper paper;
    private int degree;
    private PaperRepo paperRepo;
    private SystemConfig systemConfig;
    private HashSet<String> papers;
    private OssUtil ossUtil;
    private AliYunOssConfig aliYunOssConfig;
    private ImageServerConfig imageServerConfig;

    public RotateTask(Paper paper, int degree, PaperRepo paperRepo, SystemConfig systemConfig, HashSet<String> papers, ImageConfig imageConfig, StudentRepo studentRepo, OssUtil ossUtil, AliYunOssConfig aliYunOssConfig, ImageServerConfig imageServerConfig) {
        this.paper = paper;
        this.degree = degree;
        this.paperRepo = paperRepo;
        this.systemConfig = systemConfig;
        this.papers = papers;
        this.imageConfig = imageConfig;
        this.studentRepo = studentRepo;
        this.ossUtil = ossUtil;
        this.aliYunOssConfig = aliYunOssConfig;
        this.imageServerConfig = imageServerConfig;
    }

    @Override
    public void run() {
        long start = System.currentTimeMillis();
        try {
            String thumbPath = null;
            String thumbNew = null;
            String imagePath = null;
            String imageNew = null;
            String sliceMD5 = null;
            synchronized (paper.getId()) {
                LOGGER.info("准备生成缩略和裁切旋转图:{}", start);
                if (ParamCache.paramMap.get(paper.getWorkId()).getImageEncrypt() == 1) {
                    try {
                        Student student = studentRepo.findByWorkIdAndExamNumber(paper.getWorkId(), paper.getExamNumber());
                        String imageMd5 = MD5Util.getImageRuleMd5(paper.getWorkId(), paper.getSubject().ordinal(), paper.getAreaCode(), paper.getExamNumber(), student.getId());
                        thumbPath = systemConfig.getThumbDir() + File.separator + paper.getWorkId() + File.separator + paper.getSubject().toString()
                                + File.separator + paper.getAreaCode() + File.separator + imageMd5;
                        thumbNew = systemConfig.getThumbDir() + File.separator + paper.getWorkId() + File.separator + paper.getSubject().toString()
                                + File.separator + paper.getAreaCode() + File.separator + imageMd5;
                        imagePath = systemConfig.getImageDir() + File.separator + paper.getWorkId() + File.separator + paper.getSubject().toString()
                                + File.separator + paper.getAreaCode() + File.separator + imageMd5;
                        imageNew = systemConfig.getImageDir() + File.separator + paper.getWorkId() + File.separator + paper.getSubject().toString()
                                + File.separator + paper.getAreaCode() + File.separator + imageMd5;

                        //缩略图旋转生成
                        String thumbOldPath = thumbPath + ".jpg";
                        String thumbTempPath = thumbPath + "temp.jpg";
                        File thumbOldFile = new File(thumbOldPath);
                        //读取原图
                        File thumbTempFile = new File(thumbTempPath);
                        InputStream is = new FileInputStream(thumbOldPath);
                        OutputStream outputStream = new FileOutputStream(thumbTempPath);
                        SystemConstant.writeStream(is, outputStream);
                        is.close();
                        outputStream.flush();
                        outputStream.close();

                        //原图旋转
                        ImageCompression.rotate(thumbTempFile, thumbTempFile, degree);
                        thumbOldFile.renameTo(new File(thumbNew + "_" + start + ".jpg"));
                        thumbTempFile.renameTo(new File(thumbOldPath));
                        //加密旋转图
                        InputStream is1 = new ByteArrayInputStream(FileCopyUtils.copyToByteArray(thumbOldFile));
                        OutputStream outputStream1 = new FileOutputStream(thumbOldFile);
                        SystemConstant.writeStream(is1, outputStream1);
                        is1.close();
                        outputStream1.flush();
                        outputStream1.close();

                        //裁切原图旋转生成
                        String imageOldPath = imagePath + ".jpg";
                        String imageTempPath = imagePath + "temp.jpg";
                        File imageOldFile = new File(imageOldPath);
                        //读取原图
                        File imageTempFile = new File(imageTempPath);
                        InputStream is2 = new FileInputStream(imageOldPath);
                        OutputStream outputStream2 = new FileOutputStream(imageTempFile);
                        SystemConstant.writeStream(is2, outputStream2);
                        is2.close();
                        outputStream2.flush();
                        outputStream2.close();

                        //原图旋转
                        ImageCompression.rotate(imageTempFile, imageTempFile, degree);
                        imageOldFile.renameTo(new File(imageNew + "_" + start + ".jpg"));
                        imageTempFile.renameTo(new File(imageOldPath));
                        //加密旋转图
                        InputStream is3 = new ByteArrayInputStream(FileCopyUtils.copyToByteArray(imageOldFile));
                        OutputStream outputStream3 = new FileOutputStream(imageOldFile);
                        SystemConstant.writeStream(is3, outputStream3);
                        is3.close();
                        outputStream3.flush();
                        outputStream3.close();

                        InputStream is4 = new FileInputStream(imageOldFile);
                        sliceMD5 = DigestUtils.md5Hex(is4);
                        is4.close();
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                } else {
                    if (imageConfig.isCustomSubject() && imageServerConfig.isAliyunOss()) {
                        //阿里云oss图片旋转
                        String thumbDirName = aliYunOssConfig.getThumbDir();
                        String imageDirName = aliYunOssConfig.getImageDir();
                        thumbDirName = thumbDirName.substring(thumbDirName.indexOf(aliYunOssConfig.getBucket() + File.separator), thumbDirName.lastIndexOf("/")).replace(aliYunOssConfig.getBucket() + File.separator, "");
                        imageDirName = imageDirName.substring(imageDirName.indexOf(aliYunOssConfig.getBucket() + File.separator), imageDirName.lastIndexOf("/")).replace(aliYunOssConfig.getBucket() + File.separator, "");
                        StringJoiner thumbSj = new StringJoiner("").add(thumbDirName).add(File.separator).add(String.valueOf(paper.getWorkId())).add(File.separator).add(paper.getSubject().toString()).add(File.separator).add(paper.getAreaCode()).add(File.separator).add(paper.getExamNumber()).add(".jpg");
                        StringJoiner thumbNewSj = new StringJoiner("").add(thumbDirName).add(File.separator).add(String.valueOf(paper.getWorkId())).add(File.separator).add(paper.getSubject().toString()).add(File.separator).add(paper.getAreaCode()).add(File.separator).add(paper.getExamNumber()).add("_").add(String.valueOf(start)).add(".jpg");
                        StringJoiner imageSj = new StringJoiner("").add(imageDirName).add(File.separator).add(String.valueOf(paper.getWorkId())).add(File.separator).add(paper.getSubject().toString()).add(File.separator).add(paper.getAreaCode()).add(File.separator).add(paper.getExamNumber()).add(".jpg");
                        StringJoiner imageNewSj = new StringJoiner("").add(imageDirName).add(File.separator).add(String.valueOf(paper.getWorkId())).add(File.separator).add(paper.getSubject().toString()).add(File.separator).add(paper.getAreaCode()).add(File.separator).add(paper.getExamNumber()).add("_").add(String.valueOf(start)).add(".jpg");

                        thumbPath = systemConfig.getThumbDir() + File.separator + paper.getWorkId() + File.separator + paper.getSubject().toString()
                                + File.separator + paper.getAreaCode() + File.separator + paper.getExamNumber() + ".jpg";
                        imagePath = systemConfig.getImageDir() + File.separator + paper.getWorkId() + File.separator + paper.getSubject().toString()
                                + File.separator + paper.getAreaCode() + File.separator + paper.getExamNumber() + ".jpg";
                        File thumbFile = ossUtil.ossDownload(thumbSj.toString(), thumbPath);
                        File imageFile = ossUtil.ossDownload(imageSj.toString(), imagePath);
                        ImageCompression.rotate(thumbFile, new File(thumbPath), degree);
                        ImageCompression.rotate(imageFile, new File(imagePath), degree);
                        FileInputStream in = new FileInputStream(new File(imagePath));
                        sliceMD5 = DigestUtils.md5Hex(in);
                        in.close();
                        ossUtil.ossCopy(thumbSj.toString(), thumbNewSj.toString());
                        ossUtil.ossCopy(imageSj.toString(), imageNewSj.toString());
                        ossUtil.ossUpload(thumbSj.toString(), new FileInputStream(thumbFile));
                        ossUtil.ossUpload(imageSj.toString(), new FileInputStream(imageFile));
                        thumbFile.delete();
                        imageFile.delete();
                    } else if (!imageConfig.isCustomSubject() && imageServerConfig.isAliyunOss()) {
                        String fileName = paper.getExamNumber();
                        Student student = studentRepo.findByWorkIdAndExamNumberAndTest(paper.getWorkId(), paper.getExamNumber(), "0");
                        if (ParamCache.paramMap.get(paper.getWorkId()).getNameRule() == 1) {
                            fileName = MD5Util.getImageRuleMd5(paper.getWorkId(), paper.getSubject().ordinal(), student.getAreaCode(), paper.getExamNumber(), student.getId());
                        }
                        long s0 = System.currentTimeMillis();
                        LOGGER.info("===============OSS-生成缩略图、裁切图开始：原文件名{}================", fileName);

                        //阿里云oss图片旋转
                        StringJoiner thumbSj = new StringJoiner("/").add(imageServerConfig.getDir()).add(systemConfig.getThumbDir().replace("\\", "/")).add(String.valueOf(student.getWorkId())).add(paper.getSubject().name()).add(student.getAreaCode()).add(fileName + ".jpg");
                        StringJoiner thumbNewSj = new StringJoiner("/").add(imageServerConfig.getDir()).add(systemConfig.getThumbDir().replace("\\", "/")).add(String.valueOf(student.getWorkId())).add(paper.getSubject().name()).add(student.getAreaCode()).add(fileName + "_" + start + ".jpg");
                        StringJoiner imageSj = new StringJoiner("/").add(imageServerConfig.getDir()).add(systemConfig.getImageDir().replace("\\", "/")).add(String.valueOf(student.getWorkId())).add(paper.getSubject().name()).add(student.getAreaCode()).add(fileName + ".jpg");
                        StringJoiner imageNewSj = new StringJoiner("/").add(imageServerConfig.getDir()).add(systemConfig.getImageDir().replace("\\", "/")).add(String.valueOf(student.getWorkId())).add(paper.getSubject().name()).add(student.getAreaCode()).add(fileName + "_" + start + ".jpg");

                        thumbPath = systemConfig.getThumbDir() + File.separator + paper.getWorkId() + File.separator + paper.getSubject().toString()
                                + File.separator + paper.getAreaCode() + File.separator + fileName + ".jpg";
                        imagePath = systemConfig.getImageDir() + File.separator + paper.getWorkId() + File.separator + paper.getSubject().toString()
                                + File.separator + paper.getAreaCode() + File.separator + fileName + ".jpg";
                        long s1 = System.currentTimeMillis();
                        LOGGER.info("OSS-生成缩略图、裁切图：原文件名{}，从OSS下载开始", fileName);
                        File thumbFile = ossUtil.ossDownload(thumbSj.toString(), thumbPath);
                        File imageFile = ossUtil.ossDownload(imageSj.toString(), imagePath);
                        long s2 = System.currentTimeMillis();
                        LOGGER.info("OSS-生成缩略图、裁切图：原文件名{}，从OSS下载结束，耗时：{}秒，开始旋转", fileName, (s2 - s1) / 1000);
                        ImageCompression.rotate(thumbFile, new File(thumbPath), degree);
                        ImageCompression.rotate(imageFile, new File(imagePath), degree);
                        long s3 = System.currentTimeMillis();
                        LOGGER.info("OSS-生成缩略图、裁切图：原文件名{}，旋转结束，耗时：{}秒，原文件重命名开始", fileName, (s3 - s2) / 1000);
                        FileInputStream in = new FileInputStream(new File(imagePath));
                        sliceMD5 = DigestUtils.md5Hex(in);
                        in.close();
                        ossUtil.ossCopy(thumbSj.toString(), thumbNewSj.toString());
                        ossUtil.ossCopy(imageSj.toString(), imageNewSj.toString());
                        long s4 = System.currentTimeMillis();
                        LOGGER.info("OSS-生成缩略图、裁切图：原文件名{}，原文件重命名结束，耗时：{}秒，上传旋转图片开始", fileName, (s4 - s3) / 1000);
                        ossUtil.ossUpload(thumbSj.toString(), new FileInputStream(thumbFile));
                        ossUtil.ossUpload(imageSj.toString(), new FileInputStream(imageFile));
                        long s5 = System.currentTimeMillis();
                        LOGGER.info("OSS-生成缩略图、裁切图：原文件名{}，上传旋转图片结束，耗时：{}秒", fileName, (s5 - s4) / 1000);
                        LOGGER.info("===============OSS-生成缩略图、裁切图结束：原文件名{}，总耗时：{}秒================", fileName, (s5 - s0) / 1000);
                        thumbFile.delete();
                        imageFile.delete();
                    } else {
                        String fileName = paper.getExamNumber();
                        if (ParamCache.paramMap.get(paper.getWorkId()).getNameRule() == 1) {
                            Student student = studentRepo.findByWorkIdAndExamNumberAndTest(paper.getWorkId(), paper.getExamNumber(), "0");
                            fileName = MD5Util.getImageRuleMd5(paper.getWorkId(), paper.getSubject().ordinal(), student.getAreaCode(), paper.getExamNumber(), student.getId());
                        }
                        thumbPath = systemConfig.getThumbDir() + File.separator + paper.getWorkId() + File.separator + paper.getSubject().toString()
                                + File.separator + paper.getAreaCode() + File.separator + fileName + ".jpg";
                        thumbNew = systemConfig.getThumbDir() + File.separator + paper.getWorkId() + File.separator + paper.getSubject().toString()
                                + File.separator + paper.getAreaCode() + File.separator + fileName + "_" + start + ".jpg";
                        imagePath = systemConfig.getImageDir() + File.separator + paper.getWorkId() + File.separator + paper.getSubject().toString()
                                + File.separator + paper.getAreaCode() + File.separator + fileName + ".jpg";
                        imageNew = systemConfig.getImageDir() + File.separator + paper.getWorkId() + File.separator + paper.getSubject().toString()
                                + File.separator + paper.getAreaCode() + File.separator + fileName + "_" + start + ".jpg";
                        LOGGER.info("生成缩略图开始：原文件名{}，新文件名{}", fileName, fileName + "_" + start);
                        File thumbFile = new File(thumbPath);
                        if (thumbFile.exists()) {
                            LOGGER.info("生成缩略图：原文件名{}，重命名为新文件名开始", fileName);
                            thumbFile.renameTo(new File(thumbNew));
                            LOGGER.info("生成缩略图：原文件名{}，重命名为新文件名结束，开始旋转", fileName);
                            InputStream is = new FileInputStream(thumbNew);
                            ImageCompression.rotate(new File(thumbNew), new File(thumbPath), degree);
                            LOGGER.info("生成缩略图：原文件名{}，旋转结束", fileName);
                            is.close();
                        }

                        if (!thumbFile.exists()) {
                            LOGGER.info("生成缩略图：原文件名{}，目标文件丢失，还原图片开始", fileName);
                            new File(thumbNew).renameTo(thumbFile);
                            LOGGER.info("生成缩略图：原文件名{}，目标文件丢失，还原图片结束", fileName);
                        } else {
                            LOGGER.info("生成缩略图：原文件名{}，旋转成功", fileName);
                        }
                        LOGGER.info("生成缩略图结束：原文件名{}", fileName);

                        LOGGER.info("生成裁切图开始：原文件名{}，新文件名{}", fileName, fileName + "_" + start);
                        File imageFile = new File(imagePath);
                        if (imageFile.exists()) {
                            LOGGER.info("生成裁切图：原文件名{}，重命名为新文件名开始", fileName);
                            imageFile.renameTo(new File(imageNew));
                            LOGGER.info("生成裁切图：原文件名{}，重命名为新文件名结束，开始旋转", fileName);
                            InputStream is = new FileInputStream(imageNew);
                            ImageCompression.rotate(new File(imageNew), new File(imagePath), degree);
                            LOGGER.info("生成裁切图：原文件名{}，旋转结束", fileName);
                            is.close();
                        }
                        if (!imageFile.exists()) {
                            LOGGER.info("生成裁切图：原文件名{}，目标文件丢失，还原图片开始", fileName);
                            new File(imageNew).renameTo(imageFile);
                            LOGGER.info("生成裁切图：原文件名{}，目标文件丢失，还原图片结束", fileName);
                        } else {
                            LOGGER.info("生成裁切图：原文件名{}，旋转成功", fileName);
                        }
                        LOGGER.info("生成裁切图结束：原文件名{}", fileName);
                        FileInputStream in = new FileInputStream(new File(imagePath));
                        sliceMD5 = DigestUtils.md5Hex(in);
                        in.close();
                    }
                }
                long end = System.currentTimeMillis();
                LOGGER.info("生成缩略和裁切旋转图耗时：{},sliceMD5:{}", (end - start) / 1000 + "s", sliceMD5);
                paper.setSliceMD5(sliceMD5);
                paperRepo.save(paper);
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException ioe) {
            ioe.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            papers.remove(paper.getExamNumber());
        }
    }
}
