import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import com.lowagie.text.Document;
import com.lowagie.text.DocumentException;
import com.lowagie.text.Image;
import com.lowagie.text.Jpeg;
import com.lowagie.text.pdf.BaseFont;
import com.lowagie.text.pdf.PdfContentByte;
import com.lowagie.text.pdf.PdfImportedPage;
import com.lowagie.text.pdf.PdfReader;
import com.lowagie.text.pdf.PdfStamper;
import com.lowagie.text.pdf.PdfWriter;

/**
 * PDF utility class
 * Used for a number of generic functions for handling or creating PDF files.
 */
public class PdfUtil {
	
	/**
	 * Returns the base font for the PDF's.
	 * @return BaseFont
	 */
	private BaseFont getBaseFont() {
		try {
			return BaseFont.createFont(BaseFont.HELVETICA, BaseFont.CP1252, BaseFont.NOT_EMBEDDED);
		} catch (Exception e) {
			return null;
		}
	}
	
	/**
	 * Add a watermark to a PDF
	 * @param pdf the pdf to add the watermark to
	 * @param image the watermark image
	 * @return a pdf with watermark.
	 * @throws IOException problem reading or creating pdf, possibly input byte[] contains no data
	 * @throws DocumentException problems creating PDF or adding image
	 */
	public byte[] addWaterMark(byte[] pdf, byte[] image) throws IOException, DocumentException  {
		ByteArrayInputStream in = new ByteArrayInputStream(pdf);
		ByteArrayOutputStream out = new ByteArrayOutputStream();
		PdfReader reader = new PdfReader(in);
		PdfStamper stamper = new PdfStamper(reader, out);
		for (int x=1; x<= reader.getNumberOfPages(); x++) {
			PdfContentByte mark = stamper.getUnderContent(x);
            Image i = new Jpeg(image);
            mark.addImage(i, 100, 0, 0, 30, 250, 500);
		}
		stamper.close();
		return out.toByteArray();
	}
	
	/**
	 * Merge multiple PDF's into one
	 * @param files collection of pdf files
	 * @return a merged PDF file as a byte[]
	 * @throws IOException problem reading input files.
	 * @throws DocumentException problem merging files.
	 */
	public byte[] mergePdfFiles(Collection<File> files) 
		throws IOException, DocumentException  
	{
		ArrayList<InputStream> inputStreams = new ArrayList<InputStream>();
		for (File file : files) {
			inputStreams.add(new FileInputStream(file));
		}
		return this.mergePdfnputStreams(inputStreams);
	}
	
	/**
	 * Merge multiple PDF's into one
	 * @param inputstreams collection of pdf files as a inputstream
	 * @return a merged PDF file as a byte[]
	 * @throws IOException problem reading input files.
	 * @throws DocumentException problem merging files.
	 */
	public byte[] mergePdfnputStreams(Collection<InputStream> inputStreams) 
		throws IOException, DocumentException  
	{
		ByteArrayOutputStream out = new ByteArrayOutputStream();
		if (inputStreams == null || inputStreams.size() < 1) return null;
		Document doc = new Document();
		PdfWriter writer = PdfWriter.getInstance(doc, out);
		doc.open();
		PdfContentByte cb = writer.getDirectContent();
		for (InputStream input : inputStreams) {
			PdfReader reader = new PdfReader(input);
			for (int x=1; x<= reader.getNumberOfPages(); x++) {
				doc.newPage();
				PdfImportedPage page = writer.getImportedPage(reader, x);

				//determine if the page needs to be rotated
				int rotation = 	reader.getPageRotation(x);
				if (rotation == 90 || rotation == 270)
				{
					cb.addTemplate(page, 0,-1f, 1f, 0, 0, reader.getPageSizeWithRotation(x).getHeight());
				} else {
					cb.addTemplate(page, 1f, 0, 0, 1f, 0, 0);
				}
				
			}
			input.close();
		}
		out.flush();
		doc.close();
		out.close();
		return out.toByteArray();
	}
	
	/**
	 * Utilty method for reading a file and convert it to a byte[]
	 * @param file filename
	 * @return byte[] with file contents
	 * @throws Exception a problem occured
	 */
	public byte[] getFile(String file) throws Exception {
		FileInputStream fis = new FileInputStream(file);
		ByteArrayOutputStream result = new ByteArrayOutputStream();
		byte[] buffer = new byte[512];
		int count = fis.read(buffer);
		while (count > 0) {
			result.write(buffer);
			buffer = new byte[512];
			count = fis.read(buffer);
		}
		return result.toByteArray();
	}
	
	
	
	
	public static void main(String[] args) throws Exception{
		for (int i = 0; i <5; i++) {
			System.out.println("merging: " +i);
			File file1 = new File("c:\\test.pdf");
			File file2 = new File("c:\\test2.pdf");
			
			List files = new ArrayList<File>();
			files.add(file2);
			files.add(file1);
			
			PdfUtil util = new PdfUtil();
			byte[] data = util.mergePdfFiles(files);
			
			FileOutputStream fos  = new FileOutputStream(new File("c:\\test2.pdf"));
			fos.write(data);
			fos.flush();
			fos.close();
		}
		System.out.println("finished");
	}
	
	
}
