/*
 * This class is part of the book "iText in Action - 2nd Edition"
 * written by Bruno Lowagie (ISBN: 9781935182610)
 * For more info, go to: http://itextpdf.com/examples/
 * This example only works with the AGPL version of iText.
 */

package com.dniemcu;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.security.GeneralSecurityException;
import java.security.PrivateKey;
import java.security.cert.Certificate;
import java.util.Calendar;

import com.itextpdf.text.BaseColor;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Font;
import com.itextpdf.text.Image;
import com.itextpdf.text.Rectangle;
import com.itextpdf.text.pdf.PdfSignatureAppearance;
import com.itextpdf.text.pdf.PdfSignatureAppearance.RenderingMode;
import com.itextpdf.text.pdf.PdfTemplate;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.PdfStamper;
import com.itextpdf.text.pdf.security.BouncyCastleDigest;
import com.itextpdf.text.pdf.security.ExternalDigest;
import com.itextpdf.text.pdf.security.ExternalSignature;
import com.itextpdf.text.pdf.security.MakeSignature;
import com.itextpdf.text.pdf.security.MakeSignature.CryptoStandard;
import com.itextpdf.text.pdf.security.PrivateKeySignature;

public class PDFSignature {
    /**
     * Sign a PDF document.
     * @param src the path to the original PDF document
     * @param dest the path to the intermediate PDF document
     * @param chain certificate validation chain
     * @param privKey user's private key
     * @param digestAlgorithm digest algorithm
     * @param provider signature provider
     * @param subfilter filters
     * @param reason signing reason
     * @param location gps location
     * @throws GeneralSecurityException
     * @throws DocumentException
     * @throws IOException
     */
    public PdfSignatureAppearance sign(Image image, String src, String dest,
                                       Certificate[] chain, PrivateKey privKey, String digestAlgorithm, String provider,
                                       CryptoStandard subfilter, String reason, String location)
            throws GeneralSecurityException, IOException, DocumentException {

        // Creating the reader and the stamper
        PdfReader reader = new PdfReader(src);
        FileOutputStream os = new FileOutputStream(dest);
        PdfStamper stamper = PdfStamper.createSignature(reader, os, '\0');

        // Creating the appearance
        PdfSignatureAppearance appearance = stamper.getSignatureAppearance();
        appearance.setReason(reason);
        appearance.setLocation(location);
        appearance.setCertificate(chain[0]);

        // Añadir imagen
        if(image!=null)
        {
            appearance.setRenderingMode(RenderingMode.GRAPHIC_AND_DESCRIPTION);
            appearance.setSignatureGraphic(Image.getInstance(image));
        }
        else
            appearance.setRenderingMode(RenderingMode.NAME_AND_DESCRIPTION);

        Rectangle rectFirma = new Rectangle(85, 95, 500, 145);
        rectFirma.setBackgroundColor(BaseColor.YELLOW);
        appearance.setVisibleSignature(rectFirma, 1, null);
        appearance.setSignDate(Calendar.getInstance());

        // Creating the appearance for layer 0
        PdfTemplate n0 = appearance.getLayer(0);
        float x = n0.getBoundingBox().getLeft();
        float y = n0.getBoundingBox().getBottom();
        float width = n0.getBoundingBox().getWidth();
        float height = n0.getBoundingBox().getHeight();//*/
        n0.setColorFill(BaseColor.YELLOW);
        n0.rectangle(x, y, width, height);
        n0.fill();

        // Creating the signature
        ExternalSignature externalSignature = new PrivateKeySignature(privKey, digestAlgorithm, provider);
        ExternalDigest digest = new BouncyCastleDigest();

        MakeSignature.signDetached(appearance, digest, externalSignature, chain, null, null, null, 0, subfilter);

        // Closing the opened files
        stamper.close();
        reader.close();
        os.close();

        return appearance;
    }

    /**
     * Sign a PDF document.
     * @param src the path to the original PDF document
     * @param tmp the path to the intermediate PDF document     
     * @param dest the path to the signed PDF document
     * @param chain certificate validation chain
     * @param privKey user's private key
     * @param digestAlgorithm digest algorithm
     * @param provider signature provider
     * @param subfilter filters
     * @param reason signing reason
     * @param location gps location
     * @throws GeneralSecurityException
     * @throws DocumentException
     * @throws IOException
     */
    public PdfSignatureAppearance sign( Image image, String src, String tmp, String dest,
                                        Certificate[] chain, PrivateKey privKey, String digestAlgorithm,
                                        String provider, CryptoStandard subfilter, String reason, String location)
            throws GeneralSecurityException, IOException, DocumentException
    {
        // Creating the reader and the stamper
        PdfReader reader 	= new PdfReader(src);

        FileOutputStream os = null;
        PdfStamper stamper 	= PdfStamper.createSignature(reader, os, '\0', new File(dest));

        // Creating the appearance
        PdfSignatureAppearance appearance = stamper.getSignatureAppearance();
        appearance.setReason(reason);
        appearance.setLocation(location);

        Rectangle rectFirma = new Rectangle(85, 90, 500, 140);
        rectFirma.setBackgroundColor(BaseColor.YELLOW);
        appearance.setVisibleSignature(rectFirma, 1, "sig");
        appearance.setSignDate(Calendar.getInstance());

        // Añadir imagen
        if(image!=null)
        {
            // La firma es texto más una imagen
            appearance.setImage(Image.getInstance(image));
            appearance.setImageScale(1);
        }

        // Customizing the signature
        Font font = new Font();
        font.setSize(8);
        appearance.setLayer2Font(font);

        // Creating the appearance for layer 0
        PdfTemplate n0 = appearance.getLayer(0);
        float x = n0.getBoundingBox().getLeft();
        float y = n0.getBoundingBox().getBottom();
        float width = n0.getBoundingBox().getWidth();
        float height = n0.getBoundingBox().getHeight();
        n0.setColorFill(BaseColor.YELLOW);
        n0.rectangle(x, y, width, height-10);
        n0.fill();

        // Creating the signature
        ExternalSignature pks = new PrivateKeySignature(privKey, digestAlgorithm, provider);
        ExternalDigest digest = new BouncyCastleDigest();
        MakeSignature.signDetached(appearance, digest, pks, chain, null, null, null, 0, subfilter);

        // Closing the opened files
        stamper.close();
        reader.close();

        return appearance;
    }
}