package com.mortals.xhx.common.utils;

/**
 * @author: zxfei
 * @date: 2021/10/14 15:44
 * @description:
 **/

import com.aspose.words.Document;
import com.aspose.words.GraphicsQualityOptions;
import com.aspose.words.ImageSaveOptions;
import com.aspose.words.SaveFormat;
import com.mortals.framework.exception.AppException;
import com.mortals.framework.util.DateUtils;
import freemarker.template.Configuration;
import freemarker.template.Template;
import lombok.extern.slf4j.Slf4j;
import net.coobird.thumbnailator.Thumbnails;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.rendering.PDFRenderer;

import javax.imageio.ImageIO;
import javax.imageio.stream.ImageInputStream;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;


@Slf4j
public class WordUtil {

    private Configuration configure = null;

    public Configuration getConfigure() {
        return configure;
    }

    public void setConfigure(Configuration configure) {
        this.configure = configure;
    }

    public WordUtil() {
        configure = new Configuration();
        configure.setDefaultEncoding("utf-8");
    }

    /**
     * 根据word模板生成word文件
     *
     * @param dataMap     ： 数据
     * @param outFilePath ： 输出word文件地址
     * @return
     */
    public boolean createWord(Map<String, Object> dataMap, String inputFilePath, String outFilePath) {
        boolean flag = false;

        try {
            // 指定路径方式（根据某个类的相对路径指定）
            configure.setClassForTemplateLoading(this.getClass(), "/test");

            // 以utf-8的编码读取ftl文件
            Template template = configure.getTemplate(inputFilePath, "utf-8");
            Writer out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(new File(outFilePath)), "utf-8"),
                    10240);
            template.process(dataMap, out);

            out.close();

            flag = true;
        } catch (Exception e) {
            e.printStackTrace();
        }

        return flag;
    }


    public static String convertWordToJPEG(String inputFile, String jpegPath) {
        try {
            log.info("word to jpg文件转换开始,inputFile:{},jepgPath:{}：{}", inputFile, jpegPath, DateUtils.getCurrStrDateTime());
            // 转换开始前时间
            long old = System.currentTimeMillis();
            // 新建的PDF文件路径
            File file = new File(jpegPath);
            //FileOutputStream os = new FileOutputStream(file);
            // 要转换的word文档的路径
            Document doc = new Document(inputFile);
            // 全面支持DOC, DOCX, OOXML, RTF HTML, OpenDocument, PDF, EPUB, XPS, SWF 相互转换
            //doc.save(os, SaveFormat.JPEG);
            ImageSaveOptions options = new ImageSaveOptions(SaveFormat.JPEG);
            options.setResolution(256);
            GraphicsQualityOptions qualityOptions = new GraphicsQualityOptions();

            RenderingHints renderingHints = new RenderingHints(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

            qualityOptions.setRenderingHints(renderingHints);

            options.setGraphicsQualityOptions(qualityOptions);
            options.setJpegQuality(10);
            options.setPrettyFormat(true);
            options.setUseAntiAliasing(true);
            options.setUseHighQualityRendering(true);
            int pageCount = doc.getPageCount();
            log.info("转换的页数:{}", pageCount);
            List<BufferedImage> imageList = new ArrayList<BufferedImage>();
            for (int i = 0; i < pageCount; i++) {
                OutputStream output = new ByteArrayOutputStream();
                options.setPageIndex(i);
                doc.save(output, options);
                ImageInputStream imageInputStream = ImageIO.createImageInputStream(parse(output));
                imageList.add(ImageIO.read(imageInputStream));
                log.info("转换{}页完成！", i);
            }
            log.info("转换结束，开始拼接图片:{}", pageCount);
            //BufferedImage mergeImage = mergeImage(false, imageList);
            BufferedImage mergeImage = moreToOne(imageList);

            Thumbnails.of(mergeImage)
                    .scale(1f)
                    .outputQuality(0.8f).toFile(file);

            //ImageIO.write(mergeImage, "jepg", file);
            // 转换结束后时间
            /*            doc.save(jpegPath);*/
            doc.cleanup();
            long now = System.currentTimeMillis();
            log.info("文件转换结束,共耗时：" + ((now - old) / 1000.0) + "秒");
            return jpegPath;
        } catch (Exception e) {
            log.error("文件转换异常!", e);
            throw new AppException(String.format("文件转换异常! %s", e.getMessage()));
        }
    }

    public static Integer getPageByDoc(String inputFile) {
        try {
            //FileOutputStream os = new FileOutputStream(file);
            // 要转换的word文档的路径
            Document doc = new Document(inputFile);
            return doc.getPageCount();
        } catch (Exception e) {
            log.error("获取doc异常!", e);
            return 0;
        }
    }


    public static void pdfToImages(String filePath, String jpegPath) {
        log.info(String.format("pdf to images文件转换开始：%s", DateUtils.getCurrStrDateTime()));
        // 转换开始前时间
        long old = System.currentTimeMillis();
        File file = new File(jpegPath);
        List<BufferedImage> imageInfoList = new ArrayList<>();
        try (PDDocument doc = PDDocument.load(new File(filePath))) {
            PDFRenderer renderer = new PDFRenderer(doc);
            int pageCount = doc.getNumberOfPages();
            for (int i = 0; i < pageCount; i++) {
                BufferedImage image = renderer.renderImage(i);
                imageInfoList.add(image);
            }
            BufferedImage mergeImage = mergeImage(false, imageInfoList);
            ImageIO.write(mergeImage, "png", file);
            // 转换结束后时间
            long now = System.currentTimeMillis();
            //os.close();
            log.info("文件转换结束,共耗时：" + ((now - old) / 1000.0) + "秒");
        } catch (IOException e) {
            log.error("生成预览图片异常:", e);
            throw new AppException("生成预览图片异常");
        }
    }

    /**
     * 合并任数量的图片成一张图片
     *
     * @param isHorizontal true代表水平合并，fasle代表垂直合并
     * @param imgs         待合并的图片数组
     * @return
     * @throws IOException
     */
    public static BufferedImage mergeImage(boolean isHorizontal, List<BufferedImage> imgs) throws IOException {
        // 生成新图片
        BufferedImage destImage = null;
        // 计算新图片的长和高
        int allw = 0, allh = 0, allwMax = 0, allhMax = 0;
        // 获取总长、总宽、最长、最宽
        for (int i = 0; i < imgs.size(); i++) {
            BufferedImage img = imgs.get(i);
            allw += img.getWidth();

            if (imgs.size() != i + 1) {
                allh += img.getHeight() + 5;
            } else {
                allh += img.getHeight();
            }


            if (img.getWidth() > allwMax) {
                allwMax = img.getWidth();
            }
            if (img.getHeight() > allhMax) {
                allhMax = img.getHeight();
            }
        }
        // 创建新图片
        if (isHorizontal) {
            destImage = new BufferedImage(allw, allhMax, BufferedImage.TYPE_INT_RGB);
        } else {
            destImage = new BufferedImage(allwMax, allh, BufferedImage.TYPE_INT_RGB);
        }
        Graphics2D g2 = (Graphics2D) destImage.getGraphics();
        g2.setBackground(Color.LIGHT_GRAY);
        g2.clearRect(0, 0, allw, allh);
        g2.setPaint(Color.RED);

        // 合并所有子图片到新图片
        int wx = 0, wy = 0;
        for (int i = 0; i < imgs.size(); i++) {
            BufferedImage img = imgs.get(i);
            int w1 = img.getWidth();
            int h1 = img.getHeight();
            // 从图片中读取RGB
            int[] ImageArrayOne = new int[w1 * h1];
            // 逐行扫描图像中各个像素的RGB到数组中
            ImageArrayOne = img.getRGB(0, 0, w1, h1, ImageArrayOne, 0, w1);
            if (isHorizontal) {
                // 水平方向合并
                // 设置上半部分或左半部分的RGB
                destImage.setRGB(wx, 0, w1, h1, ImageArrayOne, 0, w1);
            } else {
                // 垂直方向合并
                // 设置上半部分或左半部分的RGB
                destImage.setRGB(0, wy, w1, h1, ImageArrayOne, 0, w1);
            }
            wx += w1;
            wy += h1 + 5;
        }


        return destImage;
    }

    /**
     * 将多张图片拼接成一张长图
     *
     * @return 拼接后的图片BufferedImage
     */
    public static BufferedImage moreToOne(List<BufferedImage> imgs) {
        //传入图片少于1张直接返回
        int len = imgs.size();

        //使用一个数组将图片装起来
        BufferedImage[] bufferedImages = new BufferedImage[len];
        int[][] imageArrays = new int[len][];
        for (int i = 0; i < len; i++) {
            try {
                //文件地址,可直接转换
                bufferedImages[i] = Thumbnails.of(imgs.get(i))
                        //.size(400, 600)
                        .width(595)
                        .outputQuality(0.8f)
                        .asBufferedImage();

            } catch (Exception e) {
                log.error("图片转换失败", e);
            }
            //获取图片宽高
            int width = bufferedImages[i].getWidth();
            int height = bufferedImages[i].getHeight();
            // 从图片中读取RGB
            imageArrays[i] = new int[width * height];
            imageArrays[i] = bufferedImages[i].getRGB(0, 0, width, height,
                    imageArrays[i], 0, width);
        }
        //拼接图片的宽高
        int dstHeight = 0;
        int dstWidth = bufferedImages[0].getWidth();
        for (BufferedImage bufferedImage : bufferedImages) {
            dstWidth = Math.max(dstWidth, bufferedImage.getWidth());
            dstHeight += bufferedImage.getHeight();
        }
        // 生成新图片
        BufferedImage imageNew = null;
        try {
            imageNew = new BufferedImage(dstWidth, dstHeight, BufferedImage.TYPE_INT_RGB);
            int newHeight = 0;
            for (int i = 0; i < bufferedImages.length; i++) {
                imageNew.setRGB(0, newHeight, dstWidth, bufferedImages[i].getHeight(), imageArrays[i], 0, dstWidth);
                newHeight += bufferedImages[i].getHeight();
            }
        } catch (Exception e) {
            log.error("图片拼接出错", e);
        }
        return imageNew;
    }


    public static ByteArrayInputStream parse(OutputStream out) throws Exception {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        baos = (ByteArrayOutputStream) out;
        ByteArrayInputStream swapStream = new ByteArrayInputStream(baos.toByteArray());
        return swapStream;

    }

    public static void main(String[] args) {
        String docPath = "E:\\pic\\doc\\3.docx";

        String jpgPath = "E:\\pic\\doc\\3.jpg";

        WordUtil.convertWordToJPEG(docPath, jpgPath);
/*

        String pdfPath = "E:\\pic\\pdf\\1.pdf";

        String jpgPath = "E:\\pic\\jpg\\1.jpg";


        WordUtil.pdfToImages(pdfPath, jpgPath);
*/

    }


}
