package com.xueyi.file.utils;

import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.rendering.PDFRenderer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.multipart.MultipartFile;

import javax.imageio.ImageIO;
import javax.imageio.ImageWriteParam;
import javax.imageio.ImageWriter;
import javax.servlet.http.HttpServletResponse;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;


public class PdfToImageUtil {

    private static final String TEMP_DIR = "/home/xueyi/temp";

    //支持文件格式
    public static final String SUPPORT_FILE = "pdf";
    //图片文件格式
    public static final String IMAGE_SUFFIX = "jpg"; //png
    //压缩文件格式
    public static final String ZIP_SUFFIX = "zip";
    //PDF是否为一页
    private static boolean isImage;

    private static final Logger log = LoggerFactory.getLogger(PdfToImageUtil.class);


    /**
     * 对外的开放接口，用于将PDF文件转换为图片文件压缩包进行下载
     * @param file SpringMVC获取的图片文件
     */
    public static synchronized void pdfToTransformation(MultipartFile file, HttpServletResponse response) throws Exception {
        String fileName = file.getOriginalFilename();
        if(null == fileName) return;
        String suffix = fileName.substring(fileName.lastIndexOf(".") + 1);
        log.info("文件名称：{},文件后缀：{}", fileName, suffix);
        if(!SUPPORT_FILE.equals(suffix)) return;
        isImage = false;
        File imageFile = generateFile(file);
        log.info("文件生成成功!");
//        downloadFile(imageFile, response);
    }

    /**
     * 对外的开放接口
     * @param file SpringMVC获取的图片文件
     */
    public static synchronized List<File> pdfToTransformationList(MultipartFile file) throws Exception {

        List<File> imageFiles = new ArrayList<>();
        try (PDDocument document = PDDocument.load(file.getInputStream())) {
            PDFRenderer pdfRenderer = new PDFRenderer(document);

            for (int pageIdx = 0; pageIdx < document.getNumberOfPages(); pageIdx++) {
                PDPage page = document.getPage(pageIdx);
                BufferedImage image = pdfRenderer.renderImageWithDPI(pageIdx, 300); // Set the DPI as needed

                // 保存图像到本地临时目录
                /*String imageName = "page_" + (pageIdx + 1) + ".png";
                File imageFile = saveImageToFile(image, imageName);*/
                String imageName = "page_" + (pageIdx + 1) + ".jpg";
                File imageFile = saveCompressedImage(image, imageName, 0.8f);

                imageFiles.add(imageFile);
            }
        }

        return imageFiles;
    }


    /**
     * 将PDF文件转换为多张图片并放入一个压缩包中
     * @param pdfFile SpringMVC获取的图片文件
     * @return 图片文件压缩包
     * @throws Exception 抛出异常
     */
    private static File generateFile(MultipartFile pdfFile) throws Exception {
        String fileName = pdfFile.getOriginalFilename();
        String directoryName = fileName.substring(0, fileName.lastIndexOf("."));
        File zipFile = new File(directoryName + "." + ZIP_SUFFIX);

        try (PDDocument document = PDDocument.load(pdfFile.getInputStream());
             ZipOutputStream zipOut = new ZipOutputStream(new FileOutputStream(zipFile))) {

            PDFRenderer pdfRenderer = new PDFRenderer(document);

            for (int pageIdx = 0; pageIdx < document.getNumberOfPages(); pageIdx++) {
                PDPage page = document.getPage(pageIdx);
                BufferedImage image = pdfRenderer.renderImageWithDPI(pageIdx, 300); // Set the DPI as needed

                // Convert BufferedImage to byte array
                ByteArrayOutputStream baos = new ByteArrayOutputStream();
                ImageIO.write(image, "png", baos);
                byte[] imageBytes = baos.toByteArray();

                // Add image to the ZipOutputStream
                ZipEntry zipEntry = new ZipEntry("page_" + (pageIdx + 1) + ".png");
                zipOut.putNextEntry(zipEntry);
                zipOut.write(imageBytes);
                zipOut.closeEntry();
            }

            System.out.println("PDF转换完成并压缩为：" + directoryName + "." + ZIP_SUFFIX);
        } catch (IOException e) {
            e.printStackTrace();
        }

        return zipFile;
    }

    private static File saveImageToFile(BufferedImage image, String imageName) throws IOException {
        Path tempDir = Paths.get(TEMP_DIR);
        if (!Files.exists(tempDir)) {
            Files.createDirectories(tempDir);
        }
        File imageFile = new File(TEMP_DIR, imageName);
        ImageIO.write(image, "png", imageFile);
        return imageFile;
    }


    private static File saveCompressedImage(BufferedImage image, String imageName, float compressionQuality) throws IOException {
        File tempDir = new File(TEMP_DIR);
        if (!tempDir.exists()) {
            tempDir.mkdirs();
        }

        File imageFile = new File(tempDir, imageName);

        Iterator<ImageWriter> writers = ImageIO.getImageWritersByFormatName("jpg");
        ImageWriter writer = writers.next();

        ImageWriteParam param = writer.getDefaultWriteParam();
        param.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
        param.setCompressionQuality(compressionQuality);

        ImageIO.write(image, "jpg", imageFile);

        return imageFile;
    }



    /**
     * 获取PDF页数
     * @throws IOException
     */
    public static Integer getPdfPageSize(MultipartFile file) throws IOException {
        try (PDDocument document = PDDocument.load(file.getInputStream())) {
            return document.getNumberOfPages();
        }
    }
}
