package com.ym.mec.util.pdf;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.URL;

import org.xhtmlrenderer.pdf.ITextRenderer;

import com.lowagie.text.DocumentException;
import com.lowagie.text.pdf.BaseFont;
import com.ym.mec.util.exception.UtilException;

/**
 * 若想将html文件转换成pdf文件 1、html必须符合xhtml语法规范 2、必须在文件中指定文件的编码方式
 * 3、如果需要显示中文，则必须指定字体文件，且在html文件中指定使用该字体 4、若用官方jar，则会有关中文换行的问题 OMS系统:
 * solar2.utils 创建者: gaoyong 创建时间： 2013-6-21
 */
public class PDFUtil {

	/**
	 * 通过文本文件导出pdf文件
	 * 
	 * @param baseUrl
	 *            资源存放路径
	 * @param file
	 *            输入的文件
	 * @param pdf
	 *            输出路径
	 * @param fontFamily
	 *            字体
	 * @throws IOException
	 *             如果发生 I/O 错误
	 * @throws UtilException
	 *             创建pdf文件失败
	 */
	public static void renderToPDFByFile(String baseUrl, File file, String pdf, String fontFamily) throws IOException, UtilException {
		try {
			ITextRenderer renderer = getRendererByFile(baseUrl, file, fontFamily);
			doRenderToPDF(renderer, pdf);
		} catch (DocumentException e) {
			throw new UtilException(e.getMessage(), e);
		}
	}

	/**
	 * 将文件转换成pdf字节数组
	 * 
	 * @param baseUrl
	 *            资源存放路径
	 * @param file
	 *            源文件
	 * @param fontFamily
	 *            字体
	 * @return 返回字节数组
	 * @throws IOException
	 *             如果发生 I/O 错误
	 * @throws UtilException
	 *             创建pdf文件失败
	 */
	public static byte[] renderToByteByFile(String baseUrl, File file, String fontFamily) throws IOException, UtilException {
		ITextRenderer renderer;
		try {
			renderer = getRendererByFile(baseUrl, file, fontFamily);
			return doRenderToByte(renderer);
		} catch (DocumentException e) {
			throw new UtilException(e.getMessage(), e);
		}
	}

	/**
	 * 将文件转换成pdf字节流
	 * 
	 * @param baseUrl
	 *            资源存放路径
	 * @param file
	 *            源文件
	 * @param fontFamily
	 *            字体
	 * @return 返回字节数组流
	 * @throws UtilException
	 *             创建pdf文件失败
	 * @throws IOException
	 *             如果发生 I/O 错误
	 */
	public static ByteArrayInputStream renderToInputStreamByFile(String baseUrl, File file, String fontFamily) throws UtilException, IOException {
		ITextRenderer renderer;
		try {
			renderer = getRendererByFile(baseUrl, file, fontFamily);
			return new ByteArrayInputStream(doRenderToByte(renderer));
		} catch (DocumentException e) {
			throw new UtilException(e.getMessage(), e);
		}
	}

	/**
	 * 将uri对应的资源导出为pdf
	 * 
	 * @param baseUrl
	 *            资源存放路径
	 * @param uri
	 *            源文件的位置
	 * @param pdf
	 *            最终导出的pdf文件路径
	 * @param fontFamily
	 *            字体
	 * @throws IOException
	 *             如果发生 I/O 错误
	 * @throws UtilException
	 *             创建pdf文件失败
	 */
	public static void renderToPDFByURI(String baseUrl, String uri, String pdf, String fontFamily) throws IOException, UtilException {

		ITextRenderer renderer;
		try {
			renderer = getRendererByURI(baseUrl, uri, fontFamily);
			doRenderToPDF(renderer, pdf);
		} catch (DocumentException e) {
			throw new UtilException(e.getMessage(), e);
		}
	}

	/**
	 * 将uri对应的资源转换成pdf字节数组
	 * 
	 * @param baseUrl
	 *            资源存放路径
	 * @param uri
	 *            源文件的位置
	 * @param fontFamily
	 *            字体
	 * @return 字节数组
	 * @throws IOException
	 *             如果发生 I/O 错误
	 * @throws UtilException
	 *             创建pdf文件失败
	 */
	public static byte[] renderToByteByURI(String baseUrl, String uri, String fontFamily) throws IOException, UtilException {
		ITextRenderer renderer;
		try {
			renderer = getRendererByURI(baseUrl, uri, fontFamily);
			return doRenderToByte(renderer);
		} catch (DocumentException e) {
			throw new UtilException(e.getMessage(), e);
		}
	}

	/**
	 * 将uri对应的资源转换成pdf字节流
	 * 
	 * @param baseUrl
	 *            资源存放路径
	 * @param uri
	 *            源文件的位置
	 * @param fontFamily
	 *            字体
	 * @return 字节数组流
	 * @throws UtilException
	 *             创建pdf文件失败
	 * @throws IOException
	 *             如果发生 I/O 错误
	 */
	public static ByteArrayInputStream renderToInputStreamByURI(String baseUrl, String uri, String fontFamily) throws UtilException, IOException {
		ITextRenderer renderer;
		try {
			renderer = getRendererByURI(baseUrl, uri, fontFamily);
			return new ByteArrayInputStream(doRenderToByte(renderer));
		} catch (DocumentException e) {
			throw new UtilException(e.getMessage(), e);
		}
	}

	/**
	 * 将字符串写入到pdf文件并输出
	 * 
	 * @param baseUrl
	 *            资源存放路径
	 * @param data
	 *            字符串
	 * @param pdf
	 *            最终导出的pdf文件路径
	 * @param fontFamily
	 *            字体
	 * @throws IOException
	 *             如果发生 I/O 错误
	 * @throws UtilException
	 *             创建pdf文件失败
	 */
	public static void renderToPDFByData(String baseUrl, String data, String pdf, String fontFamily) throws IOException, UtilException {

		ITextRenderer renderer;
		try {
			renderer = getRendererByData(baseUrl, data, fontFamily);
			doRenderToPDF(renderer, pdf);
		} catch (DocumentException e) {
			throw new UtilException(e.getMessage(), e);
		}
	}

	/**
	 * 将uri对应的资源转换成pdf字节数组
	 * 
	 * @param baseUrl
	 *            资源存放路径
	 * @param data
	 *            字符串
	 * @param fontFamily
	 *            字体
	 * @return 字节数组
	 * @throws IOException
	 *             如果发生 I/O 错误
	 * @throws UtilException
	 *             创建pdf文件失败
	 */
	public static byte[] renderToByteByData(String baseUrl, String data, String fontFamily) throws IOException, UtilException {
		ITextRenderer renderer;
		try {
			renderer = getRendererByData(baseUrl, data, fontFamily);
			return doRenderToByte(renderer);
		} catch (DocumentException e) {
			throw new UtilException(e.getMessage(), e);
		}
	}

	/**
	 * 将uri对应的资源转换成pdf字节流
	 * 
	 * @param baseUrl
	 *            资源存放路径
	 * @param data
	 *            字符串
	 * @param fontFamily
	 *            字体
	 * @return 字节数组流
	 * @throws UtilException
	 *             创建pdf文件失败
	 * @throws IOException
	 *             如果发生 I/O 错误
	 */
	public static ByteArrayInputStream renderToInputStreamByData(String baseUrl, String data, String fontFamily) throws UtilException, IOException {
		ITextRenderer renderer;
		try {
			renderer = getRendererByData(baseUrl, data, fontFamily);
			return new ByteArrayInputStream(doRenderToByte(renderer));
		} catch (DocumentException e) {
			throw new UtilException(e.getMessage(), e);
		}
	}

	/**
	 * 根据file生成ITextRenderer对象
	 * 
	 * @param file
	 *            源文件
	 * @param fontFamily
	 *            字体文件路径
	 * @return
	 * @throws DocumentException
	 * @throws IOException
	 */
	private static ITextRenderer getRendererByFile(String baseUrl, File file, String fontFamily) throws DocumentException, IOException {
		if (file.exists()) {
			ITextRenderer renderer = new ITextRenderer();
			URL url = new URL(baseUrl);
			File fontFamilyFile = new File(url.getPath(), fontFamily);
			if (fontFamilyFile.exists()) {
				renderer.getFontResolver().addFont(fontFamilyFile.getAbsolutePath(), BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
			}
			renderer.setDocument(file);
			renderer.getSharedContext().setBaseURL(baseUrl);
			renderer.layout();
			return renderer;
		} else {
			throw new FileNotFoundException(file.getPath());
		}
	}

	/**
	 * 根据uri获取ITextRenderer对象
	 * 
	 * @param uri
	 * @param fontFamily
	 * @return
	 * @throws DocumentException
	 * @throws IOException
	 */
	private static ITextRenderer getRendererByURI(String baseUrl, String uri, String fontFamily) throws DocumentException, IOException {
		ITextRenderer renderer = new ITextRenderer();

		URL url = new URL(baseUrl);
		File fontFamilyFile = new File(url.getPath(), fontFamily);
		if (fontFamilyFile.exists()) {
			renderer.getFontResolver().addFont(fontFamilyFile.getAbsolutePath(), BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
		}
		renderer.setDocument(uri);
		renderer.getSharedContext().setBaseURL(baseUrl);
		renderer.layout();
		return renderer;
	}

	/**
	 * 根据字符串内容获取ITextRenderer对象
	 * 
	 * @param data
	 * @param fontFamily
	 * @return
	 * @throws DocumentException
	 * @throws IOException
	 */
	private static ITextRenderer getRendererByData(String baseUrl, String data, String fontFamily) throws DocumentException, IOException {
		ITextRenderer renderer = new ITextRenderer();

		String windir = System.getenv("windir");
        String fileSeparator = System.getProperty("file.separator");
        if (windir != null && fileSeparator != null) {
            renderer.getFontResolver().addFont(windir + fileSeparator + "fonts" + fileSeparator + fontFamily, BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
        }else{
        	renderer.getFontResolver().addFont("/usr/share/fonts" + fileSeparator + fontFamily, BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
        }
        
		renderer.setDocumentFromString(data);
		renderer.getSharedContext().setBaseURL(baseUrl);
		renderer.layout();
		return renderer;
	}

	/**
	 * 将renderer对象写入pdf文件
	 * 
	 * @param renderer
	 * @param pdf
	 * @throws IOException
	 * @throws DocumentException
	 */
	private static void doRenderToPDF(ITextRenderer renderer, String pdf) throws IOException, DocumentException {
		OutputStream os = null;
		try {
			os = new FileOutputStream(pdf);
			renderer.createPDF(os);
		} finally {
			if (os != null) {
				os.close();
			}
		}
	}

	/**
	 * 将ITextRenderer对象转换成字节
	 * 
	 * @param renderer
	 * @return
	 * @throws DocumentException
	 * @throws IOException
	 */
	private static byte[] doRenderToByte(ITextRenderer renderer) throws DocumentException, IOException {
		ByteArrayOutputStream baos = null;
		byte[] array = null;
		try {
			baos = new ByteArrayOutputStream();
			renderer.createPDF(baos);
			baos.flush();
			array = baos.toByteArray();
		} finally {
			if (baos != null) {
				baos.close();
			}
		}
		return array;
	}
}
