package cn.report.pdf.sign.base;

import com.itextpdf.forms.PdfAcroForm;
import com.itextpdf.kernel.geom.Rectangle;
import com.itextpdf.kernel.pdf.*;
import com.itextpdf.kernel.pdf.annot.PdfAnnotation;
import com.itextpdf.signatures.CertificateInfo;
import com.itextpdf.signatures.PdfPKCS7;
import com.itextpdf.signatures.SignaturePermissions;
import com.itextpdf.signatures.SignatureUtil;

import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.tsp.TimeStampToken;
import java.io.IOException;
import java.security.GeneralSecurityException;
import java.security.Security;
import java.security.cert.X509Certificate;
import java.text.SimpleDateFormat;
import java.util.List;
public class SignatureInfo extends SignatureIntegrity 
{
	private SignaturePermissions inspectSignature(PdfDocument pdfDoc, SignatureUtil signUtil, PdfAcroForm form, String name, SignaturePermissions perms) throws GeneralSecurityException, IOException 
	{
		if (form.getField(name).getWidgets() != null && form.getField(name).getWidgets().size() > 0) {
			int pageNum = 0;
			Rectangle pos = form.getField(name).getWidgets().get(0).getRectangle().toRectangle();
			for (int i = 1; i <= pdfDoc.getNumberOfPages(); i++) {
				PdfPage page = pdfDoc.getPage(i);
				for (PdfAnnotation annot : page.getAnnotations()) {
					System.out.println();
					if (PdfName.Sig.equals(annot.getPdfObject().get(PdfName.FT)) && name.equals(annot.getPdfObject().get(PdfName.T).toString())) {
						pageNum = pdfDoc.getPageNumber(page);
						break;
					}
				}
			}
			if (pos.getWidth() == 0 || pos.getHeight() == 0) {
				System.out.println("Invisible signature");
			} else {
				System.out.println(String.format("Field on page %s; llx: %s, lly: %s, urx: %s; ury: %s", pageNum, pos.getLeft(), pos.getBottom(), pos.getRight(), pos.getTop()));
			}
		}

		PdfPKCS7 pkcs7 = super.verifySignature(signUtil, name);
		System.out.println("Digest algorithm: " + pkcs7.getHashAlgorithm());
		System.out.println("Encryption algorithm: " + pkcs7.getEncryptionAlgorithm());
		System.out.println("Filter subtype: " + pkcs7.getFilterSubtype());
		X509Certificate cert = (X509Certificate) pkcs7.getSigningCertificate();
		System.out.println("Name of the signer: " + CertificateInfo.getSubjectFields(cert).getField("CN"));
		if (pkcs7.getSignName() != null)
			System.out.println("Alternative name of the signer: " + pkcs7.getSignName());
		SimpleDateFormat date_format = new SimpleDateFormat("yyyy-MM-dd");
		System.out.println("Signed on: " + date_format.format(pkcs7.getSignDate().getTime()));
		if (pkcs7.getTimeStampDate() != null) {
			System.out.println("TimeStamp: " + date_format.format(pkcs7.getTimeStampDate().getTime()));
			TimeStampToken ts = pkcs7.getTimeStampToken();
			System.out.println("TimeStamp service: " + ts.getTimeStampInfo().getTsa());
			System.out.println("Timestamp verified? " + pkcs7.verifyTimestampImprint());
		}
		System.out.println("Location: " + pkcs7.getLocation());
		System.out.println("Reason: " + pkcs7.getReason());
		PdfDictionary sigDict = signUtil.getSignatureDictionary(name);
		PdfString contact = sigDict.getAsString(PdfName.ContactInfo);
		if (contact != null)
			System.out.println("Contact info: " + contact);
		perms = new SignaturePermissions(sigDict, perms);
		System.out.println("Signature type: " + (perms.isCertification() ? "certification" : "approval"));
		System.out.println("Filling out fields allowed: " + perms.isFillInAllowed());
		System.out.println("Adding annotations allowed: " + perms.isAnnotationsAllowed());
		for (SignaturePermissions.FieldLock lock : perms.getFieldLocks()) {
			System.out.println("Lock: " + lock.toString());
		}
		return perms;
	}

	public void inspectSignatures(String path) throws IOException, GeneralSecurityException {
		// System.out.println(path);
		PdfDocument pdfDoc = new PdfDocument(new PdfReader(path));
		PdfAcroForm form = PdfAcroForm.getAcroForm(pdfDoc, false);
		SignaturePermissions perms = null;
		SignatureUtil signUtil = new SignatureUtil(pdfDoc);
		List<String> names = signUtil.getSignatureNames();
		for (String name : names) {
			System.out.println("签名：" + name);
			perms = inspectSignature(pdfDoc, signUtil, form, name, perms);
		}
		System.out.println();
	}

	public static void main(String[] args) throws IOException, GeneralSecurityException {
		BouncyCastleProvider provider = new BouncyCastleProvider();
		Security.addProvider(provider);
		
		String EXAMPLE1 = "D:/test/target.pdf";
		// public static final String EXAMPLE2 = "results/chapter3/hello_cacert_ocsp_ts.pdf";
		// public static final String EXAMPLE3 = "results/chapter3/hello_token.pdf";
		//String EXAMPLE4 = "D:/test/pdfs/hello_signed4.pdf";
		// public static final String EXAMPLE5 = "results/chapter4/hello_smartcard_Signature.pdf";
		//String EXAMPLE6 = "D:/test/pdfs/field_metadata.pdf";

		SignatureInfo app = new SignatureInfo();
		app.inspectSignatures(EXAMPLE1);
		// app.inspectSignatures(EXAMPLE2);
		// app.inspectSignatures(EXAMPLE3);
		//app.inspectSignatures(EXAMPLE4);
		// app.inspectSignatures(EXAMPLE5);
		 //app.inspectSignatures(EXAMPLE6);
	}


}
