package cn.base.pdf;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletResponse;

import org.apache.log4j.Logger;

import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Element;
import com.itextpdf.text.Font;
import com.itextpdf.text.PageSize;
import com.itextpdf.text.Phrase;
import com.itextpdf.text.pdf.BaseFont;
import com.itextpdf.text.pdf.PdfPCell;
import com.itextpdf.text.pdf.PdfPTable;
import com.itextpdf.text.pdf.PdfWriter;

import cn.base.util.StringUtil;


public class ExportPDF {

	private static Logger logger = Logger.getLogger(ExportPDF.class);
	private static Font headfont;// 设置字体大小
	private static Font keyfont;// 设置字体大小
	private static Font textfont;// 设置字体大小
	private static int maxWidth; 
	static {
		// 中文格式
		BaseFont bfChinese;
		try {
			// 设置中文显示
			bfChinese = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
			headfont = new Font(bfChinese, 14, Font.BOLD);// 设置字体大小
			keyfont = new Font(bfChinese, 20, Font.BOLD);// 设置字体大小
			textfont = new Font(bfChinese, 12, Font.NORMAL);// 设置字体大小
			maxWidth = 520;
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	Document document = new Document();
	public ExportPDF() {
		
	}
	/**
	* 生成文件
	* @param file 待生成的文件名
	*/
    public ExportPDF(File file) {
        document.setPageSize(PageSize.A4);// 设置页面大小
        try {
            PdfWriter.getInstance(document, new FileOutputStream(file));
            document.open();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    
    /**
     * 生成文件
     * @param os
     */
    public ExportPDF(OutputStream os) {
    	document.setPageSize(PageSize.A4);// 设置页面大小
    	try {
    		PdfWriter.getInstance(document, os);
    		document.open();
    	} catch (Exception e) {
    		e.printStackTrace();
    	}
    }

	
	/**
     * 初始化文件
     * @param document
     * @param file
     */
	public void initFile(File file) {
		document.setPageSize(PageSize.A4);// 设置页面大小
		try {
			PdfWriter.getInstance(document, new FileOutputStream(file));
			document.open();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	/**
	 * 初始化文件
	 * @param os
	 */
	public void initFile(OutputStream os) {
		document.setPageSize(PageSize.A4);// 设置页面大小
		try {
			PdfWriter.getInstance(document, os);
			document.open();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * 为表格添加一个内容
	 * 
	 * @param value
	 *            值
	 * @param font
	 *            字体
	 * @param align
	 *            对齐方式
	 * @return 添加的文本框
	 */
	public PdfPCell createCell(String value, Font font, int align) {
		PdfPCell cell = new PdfPCell();
		cell.setVerticalAlignment(Element.ALIGN_MIDDLE);
		cell.setHorizontalAlignment(align);
		cell.setPhrase(new Phrase(value, font));
		return cell;
	}

	/**
	 * 为表格添加一个内容
	 * 
	 * @param value
	 *            值
	 * @param font
	 *            字体
	 * @return 添加的文本框
	 */
	public PdfPCell createCell(String value, Font font) {
		PdfPCell cell = new PdfPCell();
		cell.setVerticalAlignment(Element.ALIGN_MIDDLE);
		cell.setHorizontalAlignment(Element.ALIGN_CENTER);
		cell.setPhrase(new Phrase(value, font));
		return cell;
	}

	/**
	 * 为表格添加一个内容
	 * 
	 * @param value
	 *            值
	 * @param font
	 *            字体
	 * @param align
	 *            对齐方式
	 * @param colspan
	 *            占多少列
	 * @return 添加的文本框
	 */
	public PdfPCell createCell(String value, Font font, int align, int colspan) {
		PdfPCell cell = new PdfPCell();
		cell.setVerticalAlignment(Element.ALIGN_MIDDLE);
		cell.setHorizontalAlignment(align);
		cell.setColspan(colspan);
		cell.setPhrase(new Phrase(value, font));
		return cell;
	}

	/**
	 * 为表格添加一个内容
	 * 
	 * @param value
	 *            值
	 * @param font
	 *            字体
	 * @param align
	 *            对齐方式
	 * @param colspan
	 *            占多少列
	 * @param boderFlag
	 *            是否有有边框
	 * @return 添加的文本框
	 */
	public PdfPCell createCell(String value, Font font, int align, int colspan, boolean boderFlag) {
		PdfPCell cell = new PdfPCell();
		cell.setVerticalAlignment(Element.ALIGN_MIDDLE);
		cell.setHorizontalAlignment(align);
		cell.setColspan(colspan);
		cell.setPhrase(new Phrase(value, font));
		cell.setPadding(3.0f);
		if (!boderFlag) {
			cell.setBorder(0);
			cell.setPaddingTop(15.0f);
			cell.setPaddingBottom(8.0f);
		}
		return cell;
	}

	/**
	 * 创建一个表格对象
	 * 
	 * @param colNumber
	 *            表格的列数
	 * @return 生成的表格对象
	 */
	public PdfPTable createTable(int colNumber) {
		PdfPTable table = new PdfPTable(colNumber);
		try {
			table.setTotalWidth(maxWidth);
			table.setLockedWidth(true);
			table.setHorizontalAlignment(Element.ALIGN_CENTER);
			table.getDefaultCell().setBorder(1);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return table;
	}

	public PdfPTable createTable(float[] widths) {
		PdfPTable table = new PdfPTable(widths);
		try {
			table.setTotalWidth(maxWidth);
			table.setLockedWidth(true);
			table.setHorizontalAlignment(Element.ALIGN_CENTER);
			table.getDefaultCell().setBorder(1);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return table;
	}

	public PdfPTable createBlankTable() {
		PdfPTable table = new PdfPTable(1);
		table.getDefaultCell().setBorder(0);
		table.addCell(createCell("", keyfont));
		table.setSpacingAfter(20.0f);
		table.setSpacingBefore(20.0f);
		return table;
	}

	public <T> void generatePDF(String[] head, List<T> list, int colNum) {
		Class classType = list.get(0).getClass();
		// 创建一个只有colNum列的表格
		PdfPTable table = createTable(colNum);
		// 添加备注,靠左，不显示边框
		table.addCell(createCell("APP信息列表：", keyfont, Element.ALIGN_LEFT, colNum, false));
		// 设置表头
		for (int i = 0; i < colNum; i++) {
			table.addCell(createCell(head[i], keyfont, Element.ALIGN_CENTER));
		}

		if (null != list && list.size() > 0) {
			int size = list.size();
			for (int i = 0; i < size; i++) {
				T t = list.get(i);
				for (int j = 0; j < colNum; j++) {
					// 获得首字母
					String firstLetter = head[j].substring(0, 1).toUpperCase();
					// 获得get方法,getName,getAge等
					String getMethodName = "get" + firstLetter + head[j].substring(1);
					Method method;
					try {
						// 通过反射获得相应的get方法，用于获得相应的属性值
						method = classType.getMethod(getMethodName, new Class[] {});
						try {
							System.out.print(getMethodName + ":" + method.invoke(t, new Class[] {}) + ",");
							// 添加数据
							table.addCell(createCell(method.invoke(t, new Class[] {}).toString(), textfont));
						} catch (IllegalArgumentException e) {
							e.printStackTrace();
						} catch (IllegalAccessException e) {
							e.printStackTrace();
						} catch (InvocationTargetException e) {
							e.printStackTrace();
						}
					} catch (SecurityException e) {
						e.printStackTrace();
					} catch (NoSuchMethodException e) {
						e.printStackTrace();
					}
				}

				System.out.println("");
			}
		}

		try {
			// 将表格添加到文档中
			document.add(table);
		} catch (DocumentException e) {
			e.printStackTrace();
		} 
			// 关闭流
			document.close();
	}

	/**
	 * 提供外界调用的接口，生成以head为表头，list为数据的pdf
	 * 
	 * @param head 数据表头
	 * @param list 数据
	 * @param savePath 存储的根目录
	 * @return excel所在的路径
	 */
	public <T> String generatePDFs(String[] head, List<T> list,String savePath,String fileName) {
		final String FilePath = "pdfPath";
		String saveFilePathAndName = savePath + File.separator + fileName;

		// 获得存储的根目录
//		String savePath = new GetFilePlace().getFileDirFromProperties(FilePath);

		// 获得当天存储的路径,不存在则生成当天的文件夹
//		String realSavePath = new GenerateFold().getFold(savePath);

//		saveFilePathAndName = new GenerateFileName().generateFileName(realSavePath, "pdf");

		File file = new File(saveFilePathAndName);
		try {
			file.createNewFile();
		} catch (IOException e1) {
			e1.printStackTrace();
		}
		initFile(file);
		try {
			file.createNewFile(); // 生成一个pdf文件
		} catch (IOException e) {
			e.printStackTrace();
		}
		new ExportPDF(file).generatePDF(head, list, head.length);

		return saveFilePathAndName;
	}
	/**
	 * 导出pdf文件
	 * @param fileMap 
	 * @param headerList
	 * @param footerList
	 * @param listData
	 * @param responses
	 */
	public void exportCommPDF(Map<String, String> fileMap, List<String> headerList, List footerList,
			List<Map> listData, HttpServletResponse responses) {
		OutputStream os = null;
		try {
			os = responses.getOutputStream();
			responses.reset();// 清空输出流
			String fileName = fileMap.get("fileName").toString();
			responses.setCharacterEncoding("utf-8");
	        responses.setHeader("Content-type", "application/pdf;charset=utf-8"); 
	        fileName = toUtf8String(fileName);
	        responses.addHeader("Content-Disposition","attachment;filename=" +fileName+".pdf");  
			// responses.setHeader("Content-disposition", "attachment;
			// filename=" + fileName + ".xls");// 设定输出文件头
			// responses.setContentType("application/msexcel");// 定义输出类型
			//生成文档
			initFile(os);
			//1、生成表格
			PdfPTable table = createTable(headerList.size());
			// 添加备注,靠左，不显示边框
			table.addCell(createCell(fileMap.get("sheetName")+":", keyfont, Element.ALIGN_LEFT, headerList.size(), false));
			table.addCell(createCell(fileMap.get("header"), headfont, Element.ALIGN_CENTER, headerList.size(), true));
			//2、设置表头
			for(int i = 0 ; i < headerList.size() ; i++) {
	            table.addCell(createCell(headerList.get(i), textfont, Element.ALIGN_CENTER));
	        }
			//3、添加内容
			for(int i=0;i<listData.size();i++){
				for(int j = 0 ; j < headerList.size() ; j++) {
		            table.addCell(createCell(StringUtil.transEmpty(listData.get(i).get(headerList.get(j))+""), textfont));
		        }
			}
			//4、添加表格尾部
			if(footerList!=null && footerList.size()>0){
				table.addCell(createCell(StringUtil.transEmpty(footerList.get(0)+""), textfont, Element.ALIGN_CENTER, 2));
				for(int i=2;i<footerList.size();i++){
					table.addCell(createCell(StringUtil.transEmpty(footerList.get(i)+""), textfont));
				}
			}
			document.add(table);
			os.flush();
			document.close();
			logger.info("成功导出PDF!");
		} catch (Exception ex) {
			logger.error("导出PDF出错了", ex);
		} finally {
			try {
				os.close();
			} catch (Exception ex) {
				logger.error("关闭资源失败", ex);
			}
		}
	}
	/**
	 * 导出pdf文件
	 * @param fileMap 
	 * @param headerList
	 * @param footerList
	 * @param listData
	 * @param responses
	 */
	public void exportCommPDF(Map<String, String> fileMap, String[] headerArr, List footerList,int colspan,
			String[][] expArr, HttpServletResponse responses) {
		OutputStream os = null;
		try {
			os = responses.getOutputStream();
			responses.reset();// 清空输出流
			String fileName = fileMap.get("fileName").toString();
			responses.setCharacterEncoding("utf-8");
			responses.setHeader("Content-type", "application/pdf;charset=utf-8"); 
			fileName = toUtf8String(fileName);
			responses.addHeader("Content-Disposition","attachment;filename=" +fileName+".pdf");  
			// responses.setHeader("Content-disposition", "attachment;
			// filename=" + fileName + ".xls");// 设定输出文件头
			// responses.setContentType("application/msexcel");// 定义输出类型
			//生成文档
			initFile(os);
			//1、生成表格
			PdfPTable table = createTable(headerArr.length);
			// 添加备注,靠左，不显示边框
			table.addCell(createCell(fileMap.get("sheetName")+":", keyfont, Element.ALIGN_LEFT, headerArr.length, false));
			table.addCell(createCell(fileMap.get("header"), headfont, Element.ALIGN_CENTER, headerArr.length, true));
			//2、设置表头
			for(int i = 0 ; i < headerArr.length ; i++) {
				table.addCell(createCell(headerArr[i], textfont, Element.ALIGN_CENTER));
			}
			//3、添加内容
			for(int i=0;i<expArr.length;i++){
				for(int j = 0 ; j < expArr[i].length ; j++) {
					table.addCell(createCell(expArr[i][j], textfont));
				}
			}
			//4、添加表格尾部
			if(footerList!=null && footerList.size()>0){
				table.addCell(createCell(StringUtil.transEmpty(footerList.get(0)+""), textfont, Element.ALIGN_CENTER, colspan));
				for(int i=colspan;i<footerList.size();i++){
					table.addCell(createCell(StringUtil.transEmpty(footerList.get(i)+""), textfont));
				}
			}
			document.add(table);
			os.flush();
			document.close();
			logger.info("成功导出PDF!");
		} catch (Exception ex) {
			logger.error("导出PDF出错了", ex);
		} finally {
			try {
				os.close();
			} catch (Exception ex) {
				logger.error("关闭资源失败", ex);
			}
		}
	}
	// 把字符串转成utf8编码，保证中文文件名不会乱码
	public static String toUtf8String(String s) {
		StringBuffer sb = new StringBuffer();
		for (int i = 0; i < s.length(); i++) {
			char c = s.charAt(i);
			if (c >= 0 && c <= 255) {
				sb.append(c);
			} else {
				byte[] b;
				try {
					b = Character.toString(c).getBytes("utf-8");
				} catch (Exception ex) {
					b = new byte[0];
				}
				for (int j = 0; j < b.length; j++) {
					int k = b[j];
					if (k < 0)
						k += 256;
					sb.append("%" + Integer.toHexString(k).toUpperCase());
				}
			}
		}
		return sb.toString();
	}
}
