package com.pcloud.common.utils.pdf;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import com.google.common.collect.Lists;
import com.itextpdf.text.Chunk;
import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Font;
import com.itextpdf.text.Image;
import com.itextpdf.text.PageSize;
import com.itextpdf.text.Paragraph;
import com.itextpdf.text.Phrase;
import com.itextpdf.text.Rectangle;
import com.itextpdf.text.pdf.BaseFont;
import com.itextpdf.text.pdf.PdfContentByte;
import com.itextpdf.text.pdf.PdfPCell;
import com.itextpdf.text.pdf.PdfPTable;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.PdfStamper;
import com.itextpdf.text.pdf.PdfWriter;
import com.pcloud.common.constant.FilePathConst;
import com.pcloud.common.entity.UploadResultInfo;
import com.pcloud.common.exceptions.BizException;
import com.pcloud.common.exceptions.FileException;
import com.pcloud.common.utils.FileUtils;
import com.pcloud.common.utils.ListUtils;
import com.pcloud.common.utils.UUIDUitl;
import com.pcloud.common.utils.aliyun.OssUtils;
import com.pcloud.common.utils.pdf.po.PdfChunkPO;
import com.pcloud.common.utils.pdf.po.PdfImagePO;
import com.pcloud.common.utils.pdf.po.PdfPO;
import com.pcloud.common.utils.pdf.po.PdfTablePO;
import com.pcloud.common.utils.string.StringUtil;

/**
 * @author Administrator
 */
@Component("pdfUtils")
public class PdfUtils {

	/**
	 *
	 */
	private static final Logger LOGGER = LoggerFactory.getLogger(PdfUtils.class);

	/**
	 * PDF转换图片的宽度
	 */
	public static final Integer IMAGE_WITH = 1654;

	/**
	 * PDF转换图片的高度
	 */
	public static final Integer IMAGE_HEIGHT = 2399;

	/**
	 * PDF文件转换图片
	 *
	 * @param fileUrl
	 * @param format
	 * @return
	 * @throws Exception
	 */
	@Deprecated
	public static List<UploadResultInfo> pdfToImage(String fileUrl, String format) throws FileException {
		if (StringUtil.isEmpty(fileUrl))
			return null;
		if (!StringUtil.isEmpty(fileUrl))
			return null;
		String fileName = FileUtils.getFileName(fileUrl);
		// 下载PDF文件
		byte[] bytes = FileUtils.downloadByteFromUrl(fileUrl);
		if (bytes == null) {
			throw new FileException(FileException.FILE_DOWNLOAD_FAILURE, "下载文件失败");
		}
		if (bytes.length == 0) {
			return Lists.newArrayList();
		}
		// 解析PDF文件
		String outPath = pdfConvert(bytes, fileName, "", format);
		// 上传图片文件
		return pdfImageUpload(outPath, fileName, format);
	}

	/**
	 * PDF转换文件
	 *
	 * @param b
	 * @param fileName
	 * @param prefix
	 * @param format
	 * @return
	 * @throws Exception
	 */
	private static String pdfConvert(byte[] b, String fileName, String prefix, String format) throws FileException {
		// 解析PDF文件
		String outPath = FilePathConst.PDF_PATH + fileName + "_" + UUIDUitl.generateString(12);
		File fi = new File(outPath);
		if (!fi.exists()) {
			fi.mkdirs();
		}
		try {
			// PdfToImage pImage = new PdfToImage(IMAGE_WITH, IMAGE_HEIGHT, prefix, format);
			// pImage.convertPagesToHiResImages(b, outPath);
		} catch (Exception e) {
			FileUtils.deleteDirectory(outPath);
			LOGGER.error("【PDF】PDF转换图片失败:" + e.getMessage(), e);
			throw new FileException(FileException.FILE_CONTENT_ERROR, "PDF转换图片失败");
		}
		return outPath;
	}

	/**
	 * PDF图片上传
	 *
	 * @param outPath
	 * @param format
	 * @return
	 * @throws Exception
	 */
	private static List<UploadResultInfo> pdfImageUpload(String outPath, String fileName, String format)
			throws FileException {
		List<UploadResultInfo> list = Lists.newArrayList();
		try {
			File[] fileArray = new File(outPath).listFiles();
			for (int i = 0; i < fileArray.length; i++) {
				// modify by songx at 2017-05-19
				// PDF工具包生成的图片已pageXXX命名，所以取XXX为文件的页数
				String childDileName = FileUtils.getFileName(fileArray[i].getName());
				int page = Integer.valueOf(childDileName.replace("page", ""));
				UploadResultInfo uploadResultInfo = OssUtils.uploadLocalFile4CustomName(fileArray[i].getPath(),
						fileName + "_" + page);
				if (uploadResultInfo == null) {
					throw new FileException(FileException.FILE_CONTENT_ERROR, "PDF转换图片上传失败：第" + i + "张");
				}
				uploadResultInfo.setFileName(childDileName);
				uploadResultInfo.setFileType(format);
				uploadResultInfo.setPage(page);
				list.add(uploadResultInfo);
			}
		} catch (Exception e) {
			LOGGER.error("【PDF】PDF转换图片上传失败:" + e.getMessage(), e);
			throw new FileException(FileException.FILE_UPLOAD_FAILURE, "PDF转换图片上传失败");
		} finally {
			FileUtils.deleteDirectory(outPath);
		}
		return list;
	}

	/**
	 * 创建PDF
	 *
	 * @param pdfChunkDOs
	 * @return
	 * @throws Exception
	 */
	public static String create(List<PdfPO> pdfPOs) throws FileException {
		LOGGER.info("【PDF】创建PDF文档,<START>");
		if (ListUtils.isEmpty(pdfPOs)) {
			return null;
		}
		String outPath = null;
		PdfWriter pdfWriter = null;
		Document document = null;
		OutputStream os = null;
		try {
			// 输出路径
			outPath = FilePathConst.PDF_PATH + UUIDUitl.taskName() + ".pdf";
			FileUtils.creatFiles(outPath);
			// 创建输出流
			os = new FileOutputStream(new File(outPath));
			// 初始化文档
			// 设置纸张
			Rectangle rect = new Rectangle(PageSize.A4);
			// 创建文档实例
			document = new Document(rect, 50, 50, 50, 50);
			pdfWriter = PdfWriter.getInstance(document, os);
			document.open();
			document.newPage();
			// 添加内容添加PDF实例中
			addChunks(pdfPOs, document);
		} catch (Exception e) {
			FileUtils.deleteFile(outPath);
			LOGGER.error("【PDF】创建PDF文档失败:" + e.getMessage(), e);
			throw new FileException(FileException.FILE_CONTENT_ERROR, e.getMessage());
		} finally {
			close(document, os, pdfWriter);
		}
		LOGGER.info("【PDF】创建PDF文档,<END>");
		return outPath;
	}

	/**
	 * 添加内容到PDF中
	 *
	 * @param pdfPOs
	 * @param document
	 * @throws BizException
	 * @throws DocumentException
	 * @throws MalformedURLException
	 * @throws IOException
	 */
	private static void addChunks(List<PdfPO> pdfPOs, Document document)
			throws BizException, DocumentException, MalformedURLException, IOException {
		for (PdfPO pdfPO : pdfPOs) {
			if (pdfPO instanceof PdfChunkPO) {
				addChunk(pdfPO, document);
			} else if (pdfPO instanceof PdfTablePO) {
				addTable(pdfPO, document);
			} else if (pdfPO instanceof PdfImagePO) {
				addImage(pdfPO, document);
			}
		}
	}

	/**
	 * 添加块
	 *
	 * @param pdfPO
	 * @throws BizException
	 * @throws DocumentException
	 */
	private static void addChunk(PdfPO pdfPO, Document document) throws BizException, DocumentException {
		PdfChunkPO pdfChunkPO = (PdfChunkPO) pdfPO;
		// 段落
		Paragraph paragraph = null;
		Font font = PdfFontUtils.getByType(pdfChunkPO.getPdfFontEnum());
		if (pdfChunkPO.isLeanding()) {
			paragraph = new Paragraph(pdfChunkPO.getText(), font);
			paragraph.setLeading(pdfChunkPO.getLeading() > 0 ? pdfChunkPO.getLeading() : Float.NaN);
		} else {
			paragraph = new Paragraph();
			// 短语
			Phrase phrase = new Phrase();
			// 短语中的某一块
			Chunk chunk = new Chunk(StringUtil.isEmpty(pdfChunkPO.getText()) ? "" : pdfChunkPO.getText(), font);
			// skew大于0 的时候生效.字体倾斜角度
			if (pdfChunkPO.getSkew() > 0) {
				chunk.setSkew(0, pdfChunkPO.getSkew());
			}
			// 将块添加到短语
			phrase.add(chunk);
			// 将短语添加到段落
			paragraph.add(phrase);
		}
		// 段落前间距
		paragraph.setSpacingBefore(pdfChunkPO.getSpacingBefore() > 0 ? pdfChunkPO.getSpacingBefore() : Float.NaN);
		// 段落后间距
		paragraph.setSpacingAfter(pdfChunkPO.getSpacingAfter() > 0 ? pdfChunkPO.getSpacingAfter() : Float.NaN);
		// 段落位置
		paragraph.setAlignment(pdfChunkPO.getPdfAlignEnum().value);
		// 将段落添加到文档
		document.add(paragraph);

	}

	/**
	 * 添加表格
	 *
	 * @param pdfPO
	 * @throws BizException
	 * @throws DocumentException
	 */
	private static void addTable(PdfPO pdfPO, Document document) throws BizException, DocumentException {
		PdfTablePO pdfTablePO = (PdfTablePO) pdfPO;
		String[][] contents = pdfTablePO.getContents();
		if (contents == null || contents.length < 1) {
			return;
		}
		int rowNum = contents.length; // 总行数
		int colNum = pdfTablePO.getColumnWidths().length; // 总列数
		if (colNum < 1) {
			throw new FileException(FileException.FILE_CONTENT_ERROR, "表格列数与内容列数不一致");
		}
		// 字体
		Font font = PdfFontUtils.getByType(pdfTablePO.getPdfFontEnum());
		// 创建表格
		PdfPTable table = new PdfPTable(colNum);
		table.setTotalWidth(pdfTablePO.getColumnWidths()); // 设置列宽
		table.setLockedWidth(true); // 锁定列宽
		// 设置行和列
		for (int i = 0; i < rowNum; i++) {
			String[] cols = contents[i];
			for (int j = 0; j < colNum; j++) {
				String text = (j >= cols.length || StringUtil.isEmpty(cols[j])) ? "" : cols[j];
				// 填充单元格内容
				PdfPCell cell = new PdfPCell(new Phrase(text, font));
				// 设置上边的边框宽度
				cell.setBorderWidthTop(1);
				// 设置左边的边框宽度
				cell.setBorderWidthLeft(1);
				// 设置右边的边框宽度
				if (j == (colNum - 1)) {
					cell.setBorderWidthRight(1);
				}
				// 设置底部的边框宽度
				if (i == (rowNum - 1)) {
					cell.setBorderWidthBottom(1);
				}
				// 设置单元格高度
				cell.setMinimumHeight(pdfTablePO.getMinimumHeight() > 0 ? pdfTablePO.getMinimumHeight() : Float.NaN);
				// 设置可以居中
				cell.setUseAscender(true);
				// 设置水平居中
				cell.setHorizontalAlignment(pdfTablePO.getPdfAlignEnum().value);
				// 设置垂直居中
				cell.setVerticalAlignment(PdfPCell.ALIGN_MIDDLE);
				table.addCell(cell);
			}
		}
		// 将表格添加到文档
		document.add(table);
	}

	/**
	 * 添加图片
	 *
	 * @param pdfPO
	 * @param document
	 * @throws MalformedURLException
	 * @throws IOException
	 * @throws DocumentException
	 */
	private static void addImage(PdfPO pdfPO, Document document)
			throws MalformedURLException, IOException, DocumentException {
		PdfImagePO pdfImagePO = (PdfImagePO) pdfPO;
		Image image = null;
		if (!StringUtil.isEmpty(pdfImagePO.getImageUrl())) {
			if (pdfImagePO.getImageUrl().startsWith("http")) {
				image = Image.getInstance(new URL(pdfImagePO.getImageUrl()));
			} else {
				image = Image.getInstance(pdfImagePO.getImageUrl());
			}
			image.setAlignment(pdfImagePO.getPdfAlignEnum().value);
			if (pdfImagePO.getHeight() > 0 || pdfImagePO.getWidth() > 0) {
				image.scaleAbsolute(pdfImagePO.getHeight(), pdfImagePO.getWidth());
			}
		} else if (pdfImagePO.getImageByte() != null) {
			image = Image.getInstance(pdfImagePO.getImageByte());
		} else {
			return;
		}
		// 将表格添加到文档
		document.add(image);
	}

	/**
	 * 加水印（字符串）
	 *
	 * @param inputFile
	 *            需要加水印的PDF路径
	 * @param outputFile
	 *            输出生成PDF的路径
	 * @param waterMarkName
	 *            水印字符
	 */
	public static void stringWaterMark(String filePath, String waterMarkName) {
		PdfReader reader = null;
		PdfStamper stamper = null;
		OutputStream os = null;
		try {
			reader = new PdfReader(filePath);
			os = new FileOutputStream(filePath);
			stamper = new PdfStamper(reader, os);
			// 添加中文字体
			BaseFont bfChinese = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
			int total = reader.getNumberOfPages() + 1;

			PdfContentByte under;
			int j = waterMarkName.length();
			char c = 0;
			int rise = 0;
			// 给每一页加水印
			for (int i = 1; i < total; i++) {
				rise = 400;
				under = stamper.getUnderContent(i);
				under.beginText();
				under.setFontAndSize(bfChinese, 30);
				under.setTextMatrix(200, 120);
				for (int k = 0; k < j; k++) {
					under.setTextRise(rise);
					c = waterMarkName.charAt(k);
					under.showText(c + "");
				}
				// 添加水印文字
				under.endText();
			}
			stamper.close();
		} catch (Exception e) {
			LOGGER.error("【PDF】添加水印字符串失败:" + e.getMessage(), e);
		} finally {
			try {
				if (os != null) {
					os.close();
				}
				if (reader != null) {
					reader.close();
				}
				if (stamper != null) {
					stamper.close();
				}
			} catch (Exception e) {
			}
		}
	}

	/**
	 * 加水印（图片）
	 *
	 * @param inputFile
	 *            需要加水印的PDF路径
	 * @param outputFile
	 *            输出生成PDF的路径
	 * @param imageFile
	 *            水印图片路径
	 */
	// public static void imageWaterMark(String inputFile, String imageFile) {
	// try {
	// String[] spe = separatePath(inputFile);
	// String outputFile = spe[0] + "_WM." + spe[1];
	//
	// PdfReader reader = new PdfReader(inputFile);
	// PdfStamper stamper = new PdfStamper(reader, new
	// FileOutputStream(outputFile));
	//
	// int total = reader.getNumberOfPages() + 1;
	//
	// Image image = Image.getInstance(imageFile);
	// image.setAbsolutePosition(-100, 0);// 坐标
	// image.scaleAbsolute(800, 1000);// 自定义大小
	// // image.setRotation(-20);//旋转 弧度
	// // image.setRotationDegrees(-45);//旋转 角度
	// // image.scalePercent(50);//依照比例缩放
	// PdfGState gs = new PdfGState();
	// gs.setFillOpacity(0.2f);// 设置透明度为0.2
	// PdfContentByte under;
	// // 给每一页加水印
	// for (int i = 1; i < total; i++) {
	// under = stamper.getUnderContent(i);
	// under.beginText();
	// // 添加水印图片
	// under.addImage(image);
	// under.setGState(gs);
	// }
	// stamper.close();
	// } catch (Exception e) {
	// e.printStackTrace();
	// }
	// }

	/**
	 * 结束关闭文件流
	 *
	 * @param document
	 * @param os
	 */
	private static void close(Document document, OutputStream os, PdfWriter pdfWriter) {
		try {
			if (document != null) {
				document.close();
				document = null;
			}
			if (os != null) {
				os.close();
				os = null;
			}
			if (pdfWriter != null) {
				pdfWriter.close();
			}
		} catch (Exception e) {
			LOGGER.error("【PDF】PDF文件流关闭失败:" + e.getMessage(), e);
		}
	}

}
