package cn.report.pdf.sign;

import java.util.Map;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.URLEncoder;
import java.util.Random;
import java.util.Map.Entry;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.codec.CharEncoding;
import com.itextpdf.barcodes.Barcode128;
import com.itextpdf.forms.PdfAcroForm;
import com.itextpdf.forms.fields.PdfFormField;
import com.itextpdf.io.image.ImageData;
import com.itextpdf.io.image.ImageDataFactory;
import com.itextpdf.kernel.colors.ColorConstants;
import com.itextpdf.kernel.font.PdfFont;
import com.itextpdf.kernel.font.PdfFontFactory;
import com.itextpdf.kernel.geom.Rectangle;
import com.itextpdf.kernel.pdf.EncryptionConstants;
import com.itextpdf.kernel.pdf.PdfDocument;
import com.itextpdf.kernel.pdf.PdfPage;
import com.itextpdf.kernel.pdf.PdfReader;
import com.itextpdf.kernel.pdf.PdfWriter;
import com.itextpdf.kernel.pdf.WriterProperties;
import com.itextpdf.kernel.pdf.canvas.PdfCanvas;
import com.itextpdf.kernel.pdf.extgstate.PdfExtGState;
import com.itextpdf.kernel.pdf.xobject.PdfFormXObject;
import com.itextpdf.layout.Canvas;
import com.itextpdf.layout.element.Image;
import com.itextpdf.layout.element.Paragraph;
import com.itextpdf.layout.property.TextAlignment;

import cn.util.core.IsKit;

public class CreatePDFUtils 
{

	//监控平台输出调式信息
	private void _outputDebugMsg(String msg){
		//log.r("2",CreatePDFUtils.class.getSimpleName(),msg);
	}


	String barCodeParam = "SHA201204A7073"; //设置条形码的字符串参数
	int barCodeX = 400;
	int barCodeY = 700;
	final int barCodeW = 120;
	final int barCodeH = 60;

	String watermarkText = "111HLG中文号码";
	private String markImagePath = "waterimg.jpg";//水印图片地址
	private float OPACITY = 0.05f;
	private static final float IAMGE_HEIGHT = 110f; // 限制水印图片的的高度
	private static final float IAMGE_WIDTH = 110f; // 限制水印图片的的宽度

	private String userPassWord = "123456";
	final static String OWNER_PASSWORD = "123456hlg";//所有者密码 

	String path = "";

	Boolean editFlag = true;//是否可以编辑
	Boolean barcodeFalg = false;
	Boolean imageFalg = false;
	Boolean passwordFalg = false;


	public static void main(String [] args) {
		//new CreatePdf_Template_ITEXT().ProduceCertificate("D:/program/Tomcat9/webapps/sam_dir/train/certificate_template/1.pdf","D:/3.pdf","userName");
		/*Map map = new HashMap();
		map.put("name", "民"); name可编辑框的字段名
		map.put("sex", "男");
		map.put("age", "12");
		new CreatePdf_iText2().CreatePDF("D:/test/2.pdf","D:/test/targetPdf.pdf",map);*/
		//new CreatePdf_iText2().exportPdf(null,map,"D:/2.pdf","D:/","targetPdf.pdf");

	}
	public boolean CreatePDF(String template,String target,Map<String,String> map)
	{
		return CreatePDF(template,target,map,"");
	}
	//依据模板生成PDF文件
	public boolean CreatePDF(String tempPdfPath,String targetPdfPath,Map<String,String> map,String OPENPWD)
	{
		boolean result = true;
		PdfDocument pdf = null;
		//PdfStamper stamper = null;
		PdfReader reader = null;
		PdfWriter writer = null;
		try {
			reader = new PdfReader(tempPdfPath);//无密码模版文件
			if(IsKit.isNullOrEmpty(OPENPWD))
				writer = new PdfWriter(targetPdfPath, new WriterProperties()
						.setStandardEncryption(userPassWord.getBytes(), OWNER_PASSWORD.getBytes(), 
								EncryptionConstants.ALLOW_PRINTING, 
								EncryptionConstants.ENCRYPTION_AES_128 | EncryptionConstants.DO_NOT_ENCRYPT_METADATA));
			else
				writer = new PdfWriter(targetPdfPath);
			// Write to PDF along with encryption properties
			//PdfWriter writer = new PdfWriter(new FileOutputStream(RESULT_PDF), props);
			pdf = new PdfDocument(reader,writer);
			//pdf = new PdfDocument(reader, new PdfWriter(targetPdfPath));
			//addImagewaterMark(pdf,ImageDataFactory.create("D:/test/2.jpg"));
			//addwaterMark(pdf,new Image(ImageDataFactory.create("D:/test/2.jpg")));
			//addTextwaterMark(pdf,watermarkText);

			PdfAcroForm  form = PdfAcroForm.getAcroForm(pdf,true);
			dataFill_Map(form, map);
			form.flattenFields();//设置表单域不可编辑
		} catch (Exception e) {
			result = false;
			_outputDebugMsg(e.getMessage());
		}finally{
			try {
				if(pdf != null)
					pdf.close();
				if(writer != null)
					writer.close();
				if(reader != null)
					reader.close();

			} catch (Exception e) {
				_outputDebugMsg(e.getMessage());
			}
		}
		return result;
	}
	public void CreatePDF(Map<String,String> map,String templateFile,String path,String fileName)
	{
		exportPdf(null,map,path,templateFile,fileName);
	}
	/**生成pdf，提示下载*/
	public void exportPdf(HttpServletResponse response,Map<String,String> map,String templateFile,String path,String fileName)
	{
		if( map == null || map.size() == 0 || templateFile == null || templateFile.length() == 0 ) 
			return;

		this.path = path;
		PdfDocument pdf = null;
		PdfReader reader = null;
		PdfWriter writer = null;
		WriterProperties props = null;
		try {
			reader = new PdfReader(templateFile);
			if(passwordFalg){// 设置密码
				props = new WriterProperties().setStandardEncryption(userPassWord.getBytes(), OWNER_PASSWORD.getBytes(), 
						EncryptionConstants.ALLOW_PRINTING,
						EncryptionConstants.ENCRYPTION_AES_128 | EncryptionConstants.DO_NOT_ENCRYPT_METADATA);
			}
			//生成的输出流 
			if(response == null) {
				if(props == null)
					writer = new PdfWriter(new FileOutputStream(new File(path + fileName)));
				else
					writer = new PdfWriter(new FileOutputStream(new File(path + fileName)),props);
			}
			else{
				// 设置response参数，可以打开下载页面
				response.reset();
				response.setContentType("application/pdf;charset=utf-8");  
				response.addHeader("Content-Disposition","attachment;filename="+URLEncoder.encode(fileName, CharEncoding.UTF_8).replace("+", "%20"));//EntityConvert.getISO(fileName));//new String( fileName.getBytes("gb2312"), "ISO8859-1")
				if(props == null)
					writer = new PdfWriter(response.getOutputStream());
				else
					writer = new PdfWriter(response.getOutputStream(),props);
			}

			pdf = new PdfDocument(new PdfReader(templateFile),writer);
			if(barcodeFalg) addBarcode(pdf);

			//添加水印
			if(imageFalg) {
				addImagewaterMark(pdf,ImageDataFactory.create(path + markImagePath));	
			}

			PdfAcroForm  form = PdfAcroForm.getAcroForm(pdf,true);
			dataFill_Map(form, map);

			form.flattenFields();//设置表单域不可编辑
		} catch (Exception e) {
			_outputDebugMsg(e.getMessage());
		}finally{
			try {
				if(writer != null)
					writer.close();
				if(pdf != null)
					pdf.close();
				if(reader != null)
					reader.close();
			} catch (IOException e) {
				_outputDebugMsg(e.getMessage());
			}	
		}
	}
	/**
	 * 将模板中的表单字段赋值
	 * 利用福昕构造交互PDF文件。其中可编辑字段的ID同Map的key完全相同，所要填写的值为对应key的value
	 */
	private void dataFill_Map(PdfAcroForm form,Map<String,String> map) throws IOException 
	{
		if(form == null ) return;
		Map<String, PdfFormField> fields = form.getFormFields();
		//处理中文问题
		String key;
		String value;
		PdfFont bf = PdfFontFactory.createFont("STSongStd-Light", "UniGB-UCS2-H", false);  
		if(fields != null)
			for (Entry<String, String> entry: map.entrySet()) {
				key = entry.getKey();
				value = entry.getValue();
				//填充文本域
				if(fields.get(key) != null)
					fields.get(key).setValue(value).setFont(bf).setFontSize(12);
			}
		/*
		java.util.Iterator<String> it = fields.keySet().iterator();
        while (it.hasNext()) {
             String name = it.next().toString();//获取文本域名称
             fields.get(name).setValue(map.get(name)).setFont(bf).setFontSize(12);//填充文本域
         }    */
		//form.flattenFields();//设置表单域不可编辑   
	}
	/**添加二维码*/
	public void addBarcode(PdfDocument pdfDoc) throws IOException//addBarcode 
	{
		PdfPage page = pdfDoc.getFirstPage();//pdfDoc.addNewPage()
		PdfCanvas canvas = new PdfCanvas(page);
		Barcode128 code128 = new Barcode128(pdfDoc);
		code128.setCode(barCodeParam);//设置条形码的字符串参数
		code128.setCodeType(Barcode128.CODE128);
		PdfFormXObject xObject = code128.createFormXObject(ColorConstants.BLACK, ColorConstants.BLACK, pdfDoc);
		float x = 36+100;
		float y = 750;
		float w = xObject.getWidth();
		float h = xObject.getHeight();
		canvas.saveState();
		canvas.setFillColor(ColorConstants.LIGHT_GRAY);
		canvas.rectangle(x, y, w, h);
		canvas.fill();
		canvas.restoreState();
		canvas.addXObject(xObject,x,y);

	}
	/**添加文字水印.itext7默认是不支持中文，pdf中的中文字体将不进行显示，需要进行字体的设置*/
	protected void addTextwaterMark(PdfDocument pdf,String text) throws IOException
	{
		//PdfFont font = PdfFontFactory.createFont(FontProgramFactory.createFont(StandardFonts.HELVETICA));
		//要创建OS支持的字体
		PdfFont font = PdfFontFactory.createFont("STSongStd-Light", "UniGB-UCS2-H", false);
		Paragraph p = new Paragraph(text).setFont(font).setFontSize(30);

		int n = pdf.getNumberOfPages();
		PdfExtGState gs1 = new PdfExtGState();
		gs1.setFillOpacity(OPACITY);
		PdfCanvas pdfCanvas = null;
		Canvas canvas = null;
		Rectangle pageSize;
		int x, y,yT;
		for (int i = 1; i <= n; i++) {  // loop over every page
			Random random = new Random();
			pageSize = pdf.getPage(i).getPageSize();
			x = (int)((pageSize.getLeft() + pageSize.getRight()) / 2);
			yT = (int)((pageSize.getTop() + pageSize.getBottom()) / 2);
			y = random.nextInt(yT);
			pdfCanvas = new PdfCanvas(pdf.getPage(i));
			pdfCanvas.saveState();
			pdfCanvas.setExtGState(gs1);
			canvas = new Canvas(pdfCanvas,pdf,pageSize);
			canvas.showTextAligned(p,x,y,TextAlignment.CENTER);
			pdfCanvas.restoreState();
		}
		if(canvas != null)
			canvas.close();
		if(pdfCanvas != null)
			pdfCanvas.release();
	}
	/**添加图片水印 */
	private void addImagewaterMark(PdfDocument pdf,ImageData img) throws IOException 
	{
		int n = pdf.getNumberOfPages();
		float w = img.getWidth();
		float h = img.getHeight();
		PdfExtGState gs1 = new PdfExtGState();
		gs1.setFillOpacity(OPACITY);
		PdfCanvas pdfCanvas = null;
		Rectangle pageSize;
		float x, y;
		for (int i = 1; i <= n; i++) {  // loop over every page
			pageSize = pdf.getPage(i).getPageSize();
			x = (pageSize.getLeft() + pageSize.getRight()) / 2;
			y = (pageSize.getTop() + pageSize.getBottom()) / 2;
			pdfCanvas = new PdfCanvas(pdf.getPage(i));
			pdfCanvas.saveState();
			pdfCanvas.setExtGState(gs1);
			pdfCanvas.addImage(img, w, 0, 0,h, x - (w / 2), y - (h / 2), true);
			pdfCanvas.restoreState();
		}
		if(pdfCanvas != null)
			pdfCanvas.release();
	}

	/**添加水印*/
	protected void addwaterMark(PdfDocument pdf,Image img)  
	{
		int n = pdf.getNumberOfPages();
		PdfPage page = pdf.getFirstPage();
		Rectangle pageSize = page.getPageSize();

		float pageHeight= (pageSize.getLeft() + pageSize.getRight()) / 2;
		float pageWidth = (pageSize.getTop() + pageSize.getBottom()) / 2;

		PdfExtGState gs1 = new PdfExtGState();
		gs1.setFillOpacity(OPACITY);

		PdfCanvas over = null;
		Canvas canvas = null;
		int lineNum = (int) (pageHeight / IAMGE_HEIGHT); // 行数
		int middleY = (int) pageWidth / 2;
		for (int i = 1; i <= n; i++) {
			for (int j = 0, k = 0; j < lineNum; j = j + 2, k++) {
				Random random = new Random();
				img.scaleAbsolute(IAMGE_WIDTH, IAMGE_HEIGHT * 184 / 455);
				over = new PdfCanvas(pdf.getPage(i));
				over.saveState();
				over.setExtGState(gs1);
				canvas = new Canvas(over, pdf, pdf.getDefaultPageSize());

				int trueY;
				while (true) {
					trueY = random.nextInt(middleY);
					if (trueY > IAMGE_WIDTH / 2	&& trueY < (middleY - IAMGE_WIDTH)) {
						break;
					}
				}
				img.setFixedPosition(trueY, j * IAMGE_HEIGHT + (float) random.nextInt((int) IAMGE_HEIGHT) - (k % 2) * 10); // 水印的位置
				img.setRotationAngle(random.nextInt(360));// 旋转 角度
				canvas.add(img);
				while (true) {
					trueY = random.nextInt(middleY) + middleY;
					if (trueY > middleY + IAMGE_WIDTH / 2 && trueY < (2 * middleY - IAMGE_WIDTH)) {
						break;
					}
				}
				img.setFixedPosition(trueY, j * IAMGE_HEIGHT + (float) random.nextInt((int) IAMGE_HEIGHT) - (k % 2) * 10); // 水印的位置
				img.setRotationAngle(random.nextInt(180));// 旋转 角度
				canvas.add(img);

				over.restoreState();
			}
		}
		if(canvas != null)
			canvas.close();
	}
	///////////////////
	public void setBarCodeParam(String barCodeParam) {
		this.barCodeParam = barCodeParam;
	}
	public void setBarCodeParam(String barCodeParam,int barCodeX,int barCodeY) {
		this.barCodeParam = barCodeParam;
		this.barCodeX = barCodeX;
		this.barCodeY = barCodeY;
	}
	public void setImageParam(String markImagePath) {
		this.markImagePath = markImagePath;
	}

	public void setPassword(String userPassWord) {
		this.userPassWord = userPassWord;
	}

	public CreatePDFUtils() {}
	public CreatePDFUtils(Boolean barcodeFalg) {
		this.barcodeFalg = barcodeFalg;
	}
	public CreatePDFUtils(Boolean barcodeFalg, Boolean imageFalg) {
		this.barcodeFalg = barcodeFalg;
		this.imageFalg = imageFalg;
	}
	public CreatePDFUtils(Boolean barcodeFalg, Boolean imageFalg, Boolean passwordFalg) {
		this.barcodeFalg = barcodeFalg;
		this.imageFalg = imageFalg;
		this.passwordFalg = passwordFalg;
	}
	public CreatePDFUtils(Boolean barcodeFalg, Boolean imageFalg, Boolean passwordFalg, Boolean editFlag) {
		this.barcodeFalg = barcodeFalg;
		this.imageFalg = imageFalg;
		this.passwordFalg = passwordFalg;
		this.editFlag = editFlag;
	}
}