package com.qmth.distributed.print.business.util;

import com.itextpdf.text.Document;
import com.itextpdf.text.Rectangle;
import com.itextpdf.text.pdf.*;
import com.qmth.boot.tools.models.ByteArray;
import com.qmth.distributed.print.business.bean.dto.PdfDto;
import com.qmth.teachcloud.common.contant.SystemConstant;
import com.qmth.teachcloud.common.enums.ExceptionResultEnum;
import com.qmth.teachcloud.common.enums.PageSizeEnum;
import com.qmth.teachcloud.common.enums.UploadFileEnum;
import com.qmth.teachcloud.common.util.JacksonUtil;
import com.sun.org.apache.bcel.internal.generic.GOTO;
import org.apache.commons.io.IOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.*;
import java.time.LocalDateTime;
import java.util.Objects;
import java.util.Optional;
import java.util.StringJoiner;

/**
 * @Description: 合并pdf util
 * @Param:
 * @return:
 * @Author: wangliang
 * @Date: 2021/4/7
 */
public class PdfUtil {
    private final static Logger log = LoggerFactory.getLogger(PdfUtil.class);

    /**
     * 将多个PDF合并成一个PDF
     *
     * @param files
     * @param outputPath
     */
    public static String mergePdf(String[] files, String outputPath) {
        if (Objects.nonNull(files)) {
            log.info("files:{},outputPath:{}", JacksonUtil.parseJson(files), outputPath);
        } else {
            log.info("files is null");
        }
        Document document = null;
        PdfCopy copy = null;
        StringJoiner dirName = null;
        try {
            if (Objects.nonNull(files) && files.length > 0) {
                document = new Document(new PdfReader(ByteArray.fromFile(new File(files[0])).value()).getPageSize(1));
                if (Objects.isNull(outputPath)) {
                    LocalDateTime nowTime = LocalDateTime.now();
                    StringJoiner stringJoiner = new StringJoiner("").add(SystemConstant.PDF_TEMP_FILES_DIR).add(File.separator);
                    dirName = new StringJoiner("")
                            .add(UploadFileEnum.PDF.getTitle()).add(File.separator)
                            .add(String.valueOf(nowTime.getYear())).add(File.separator)
                            .add(String.format("%02d", nowTime.getMonthValue())).add(File.separator)
                            .add(String.format("%02d", nowTime.getDayOfMonth()))
                            .add(File.separator).add(SystemConstant.getUuid()).add(SystemConstant.PDF_PREFIX);
                    outputPath = stringJoiner.toString() + dirName.toString();
                }
                copy = new PdfSmartCopy(document, new FileOutputStream(outputPath));
                document.open();
                for (int i = 0; i < files.length; i++) {
                    PdfReader reader = new PdfReader(ByteArray.fromFile(new File(files[i])).value());
                    int numberOfPages = reader.getNumberOfPages();
                    for (int j = 1; j <= numberOfPages; j++) {
                        document.newPage();
                        PdfImportedPage page = copy.getImportedPage(reader, j);
                        copy.addPage(page);
                    }
                    reader.close();
                }
            }
        } catch (Exception e) {
            log.error(SystemConstant.LOG_ERROR, e);
        } finally {
            if (Objects.nonNull(document)) {
                document.close();
            }
            if (Objects.nonNull(copy)) {
                copy.flush();
                copy.close();
            }
        }
        return Objects.nonNull(dirName) ? dirName.toString() : null;
    }

    /**
     * 新增pdf page
     *
     * @param pdfFile
     * @return
     * @throws IOException
     */
    public static PdfDto addPdfPage(File pdfFile) throws IOException {
        PdfReader reader = null;
        FileOutputStream fileOutputStream = null;
        int pageCount = 0;
        try {
            if (Objects.nonNull(pdfFile)) {
                reader = new PdfReader(ByteArray.fromFile(pdfFile).value());
                pageCount = reader.getNumberOfPages();
                if (Math.abs(pageCount % 2) == 1) {//取偶
                    ByteArrayOutputStream baos = new ByteArrayOutputStream();
                    PdfStamper stamper = new PdfStamper(reader, baos);
                    stamper.insertPage(pageCount + 1, reader.getPageSizeWithRotation(1));
                    stamper.close();
                    fileOutputStream = new FileOutputStream(pdfFile);
                    IOUtils.write(baos.toByteArray(), fileOutputStream);
                }
            }
        } catch (Exception e) {
            log.error(SystemConstant.LOG_ERROR, e);
        } finally {
            if (Objects.nonNull(reader)) {
                reader.close();
            }
            if (Objects.nonNull(fileOutputStream)) {
                fileOutputStream.flush();
                fileOutputStream.close();
            }
        }
        return new PdfDto(PageSizeEnum.A3, Objects.nonNull(reader) ? reader.getNumberOfPages() : 0, pageCount);
    }

    /**
     * 获取pdfPages
     *
     * @param pdfFile
     * @return
     * @throws IOException
     */
    public static int getPdfPages(File pdfFile) throws IOException {
        PdfReader reader = null;
        try {
            if (Objects.nonNull(pdfFile)) {
                reader = new PdfReader(ByteArray.fromFile(pdfFile).value());
                return reader.getNumberOfPages();
            }
        } catch (Exception e) {
            log.error(SystemConstant.LOG_ERROR, e);
        } finally {
            if (Objects.nonNull(reader)) {
                reader.close();
            }
        }
        return 0;
    }

    /**
     * 获取pdf格式
     *
     * @param file
     * @return
     * @throws IOException
     */
    public static PageSizeEnum getPdfFormat(File file) throws IOException {
        float min;
        float max;
        Optional.ofNullable(file).orElseThrow(() -> ExceptionResultEnum.ERROR.exception("文件不能为空"));
        PdfReader reader = new PdfReader(ByteArray.fromFile(file).value());
        int totalPages = reader.getNumberOfPages();
        PageSizeEnum pageSizeEnum = null;
        for (int i = 1; i <= totalPages; i++) {
            Rectangle pageSize = reader.getPageSize(i);
            float width = pageSize.getWidth();
            float height = pageSize.getHeight();
            if (width <= height) {
                min = width;
                max = height;
            } else {
                min = height;
                max = width;
            }
            if (pageSizeEnum != null) {
                if (!pageSizeEnum.equals(PageSizeEnum.convertToEnum(min, max))) {
                    throw ExceptionResultEnum.ERROR.exception("上传的试卷pdf中存在纸张格式不一样的");
                }
            } else {
                pageSizeEnum = PageSizeEnum.convertToEnum(min, max);
            }
        }

        return pageSizeEnum;
    }

//    public static void main(String[] args) {
//        String[] files = {
//                "/Users/king/Downloads/测试附件/101_148382537591291904_signAndSticker.pdf",
//                "/Users/king/Downloads/pdf/3120ee49668e4bf48fd8c161a2abb73b的副本A3.pdf",
//                "/Users/king/Downloads/测试附件/101_158277997340655616_paperPackage.pdf"
////                "/Users/king/Downloads/测试附件/101_148382537591291904_signAndSticker.pdf"
//        };
//        String outputPath = "/Users/king/Downloads/pdf/merge1.pdf";
//        PdfUtil.mergePdf(files, outputPath);
//    }

    /**
     * 两页打印到一页（A4 -> A3）
     *
     * @param streamOfPDFFile 原卷
     * @param outputStream    输出的试卷
     * @param paginate        是否生成A3 每页页码
     */
    public static void concatPDFs(InputStream streamOfPDFFile, OutputStream outputStream, boolean paginate) {

        Document document = new Document();
        try {

            //读取PDF
            InputStream pdf = streamOfPDFFile;
            PdfReader pdfReader = new PdfReader(pdf);
            int totalPages = pdfReader.getNumberOfPages();

            //创建PDF Writer
            PdfWriter writer = PdfWriter.getInstance(document, outputStream);
            document.open();
            BaseFont baseFont = BaseFont.createFont(BaseFont.HELVETICA, BaseFont.CP1252, BaseFont.NOT_EMBEDDED);
            PdfContentByte contentByte = writer.getDirectContent();

            Rectangle rec = pdfReader.getPageSize(1);
            //新pdf为两个宽度
            Rectangle newRec = new Rectangle(0, 0, rec.getWidth() * 2, rec.getHeight());
            document.setPageSize(newRec);

            PdfImportedPage page;
            PdfImportedPage page2;
            int currentPageNumber = 0;

            //舍弃奇数的最后一页, 删除该设置后面不受影响
//            totalPages = totalPages >> 1 << 1;
            for (int pageIndex = 0; pageIndex < totalPages; pageIndex += 2) {
                document.newPage();
                currentPageNumber++;

                //原始第一页设置到左边
                page = writer.getImportedPage(pdfReader, pageIndex + 1);
                contentByte.addTemplate(page, 0, 0);

                //第二页设置到右边
                if (pageIndex + 2 <= totalPages) {
                    page2 = writer.getImportedPage(pdfReader, pageIndex + 2);
                    contentByte.addTemplate(page2, rec.getWidth(), 0);
                }

                //设置页码
                if (paginate) {
                    contentByte.beginText();
                    contentByte.setFontAndSize(baseFont, 13);
                    contentByte.showTextAligned(PdfContentByte.ALIGN_CENTER, "" + currentPageNumber + "/" + (totalPages / 2 + (totalPages % 2 == 0 ? 0 : 1)), newRec.getWidth() / 2, 17, 0);
                    contentByte.endText();
                }
            }

            outputStream.flush();
            document.close();
            outputStream.close();
        } catch (Exception e) {
            log.error(SystemConstant.LOG_ERROR, e);
        } finally {
            if (document.isOpen()) {
                document.close();
            }
            try {
                if (outputStream != null) {
                    outputStream.close();
                }
            } catch (IOException ioe) {
                log.error(SystemConstant.LOG_ERROR, ioe);
            }
        }
    }
}
