package demo;

import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Iterator;
import java.util.List;

import at.gv.egiz.pdfas.PdfAsFactory;
import at.gv.egiz.pdfas.api.PdfAs;
import at.gv.egiz.pdfas.api.analyze.AnalyzeParameters;
import at.gv.egiz.pdfas.api.analyze.AnalyzeResult;
import at.gv.egiz.pdfas.api.analyze.NonTextObjectInfo;
import at.gv.egiz.pdfas.api.commons.Constants;
import at.gv.egiz.pdfas.api.commons.SignatureInformation;
import at.gv.egiz.pdfas.api.exceptions.PdfAsException;
import at.gv.egiz.pdfas.api.io.DataSource;
import at.gv.egiz.pdfas.api.verify.VerifyAfterAnalysisParameters;
import at.gv.egiz.pdfas.api.verify.VerifyResult;
import at.gv.egiz.pdfas.api.verify.VerifyResults;
import at.gv.egiz.pdfas.commandline.Main;
import at.gv.egiz.pdfas.framework.config.SettingsHelper;
import at.gv.egiz.pdfas.framework.vfilter.VerificationFilterParameters;
import at.gv.egiz.pdfas.io.FileBasedDataSource;

public class SignatureVerificationDemo {

   /**
    * Starts a demo that verifies a document.
    * 
    * @param args
    *           The parameter(s).
    */
   public static void main(String[] args) {

      if (args == null || args.length == 0) {
         System.err.println("Please provide path of file to be verified.");
         System.exit(1);
      }
      
      File configdir = new File("./work");
      File signedFile = new File(args[0]);

      try {

         // instantiate api
         PdfAs pdfasAPI = PdfAsFactory.createPdfAs(configdir);

         // set source
         DataSource dataSource = new FileBasedDataSource(signedFile, "application/pdf");

         // evaluate settings
         VerificationFilterParameters parameters = SettingsHelper.readVerificationFilterParametersFromSettings();
         String verifyMode = Constants.VERIFY_MODE_FULL_CONSERVATIVE;

         if (parameters.extractBinarySignaturesOnly()) {
            verifyMode = Constants.VERIFY_MODE_BINARY_ONLY;
         } else if (parameters.assumeOnlySignatureUpdateBlocks()) {
            verifyMode = Constants.VERIFY_MODE_SEMI_CONSERVATIVE;
         } else {
            verifyMode = Constants.VERIFY_MODE_FULL_CONSERVATIVE;
         }

         // configure analyze parameters
         AnalyzeParameters analyzeParameters = new AnalyzeParameters();
         analyzeParameters.setDocument(dataSource);
         analyzeParameters.setVerifyMode(verifyMode);
         analyzeParameters.setReturnNonTextualObjects(true);

         // analyze
         System.out.println("Analyzing...");
         AnalyzeResult analyzeResult = pdfasAPI.analyze(analyzeParameters);
         System.out.println("Successfully analyzed.");
         
         // information on non-textual objects can be used after analysis step and/or after verification
         List signatures = analyzeResult.getSignatures();
         if (signatures != null && !signatures.isEmpty()) {
            int counter = 0;
            Iterator sigIterator = signatures.iterator();
            while (sigIterator.hasNext()) {
               counter++;
               SignatureInformation sigInfo = (SignatureInformation) sigIterator.next();
               System.out.println("\n------------------------ SIGNATURE #" + counter + " ------------------------");
               if (sigInfo.hasNonTextualObjects()) {
                  System.out.println("\nWARNING: " + sigInfo.getNonTextualObjects().size() + " non textual object(s) detected for this signature.");
                  Iterator noit = sigInfo.getNonTextualObjects().iterator();
                  while (noit.hasNext()) {
                     NonTextObjectInfo info = (NonTextObjectInfo) noit.next();
                     System.out.println("  -> " + info.toString());
                  }
                  System.out.println();
                  
               } else {
                  System.out.println("\nNo non-textual objects detected for this signature.");
               }
            }
         }
         
         // setup verification
         VerifyAfterAnalysisParameters vaap = new VerifyAfterAnalysisParameters();
         vaap.setAnalyzeResult(analyzeResult);
         vaap.setReturnHashInputData(true);
         vaap.setSignatureDevice(Constants.SIGNATURE_DEVICE_MOA);
         vaap.setVerificationTime(null);

         // invoke verification
         System.out.println("Verifying...");
         VerifyResults verifyResults = pdfasAPI.verify(vaap);
         List verifyResultList = verifyResults.getResults();
         System.out.println("Verification complete.\n");

         // iterate over results
         PrintWriter out = new PrintWriter(System.out);
         Iterator it = verifyResultList.iterator();
         int counter = 0;
         while (it.hasNext()) {
            counter++;
            VerifyResult result = (VerifyResult) it.next();
            out.println("\n------------------------ SIGNATURE #" + counter + " ------------------------\n");
            Main.formatVerifyResult(result, out);
            
            // check if there are timestamps
            if (result.getTimeStampValue() != null) {
               out.println("\nTimeStamp value available for this signature");
            }
            
            // check if non textual elements have been detected for this signature
            if (result.hasNonTextualObjects()) {
               out.println("\nWARNING: " + result.getNonTextualObjects().size() + " non textual object(s) detected for this signature");
               Iterator noit = result.getNonTextualObjects().iterator();
               while (noit.hasNext()) {
                  NonTextObjectInfo info = (NonTextObjectInfo) noit.next();
                  out.println("  -> " + info.toString());
               }
               out.println();
               
            } else {
               out.println("\nNo non-textual objects detected for this signature.");
            }
         }
         out.flush();         
         
      } catch (PdfAsException e) {
         e.printStackTrace();
      } catch (IOException e) {
         e.printStackTrace();
      }

   }

}