package net.catcert.psa.test.signature;

import java.math.BigInteger;
import java.security.cert.X509Certificate;

import net.catcert.psa.services.PsaServices;
import net.catcert.psa.util.Utils;

import org.etsi.uri._01903.v1_2_2.QualifierType;
import org.etsi.uri._01903.v1_2_2.QualifierType.Enum;

import schema.core._0._1.dss.tc.names.oasis.InternationalStringType;
import schema.core._0._1.dss.tc.names.oasis.ResultDocument.Result;

import com.sadiel.catcert.psa.ws.client.SignatureServiceStub;
import com.sadiel.catcert.psa.ws.client.factory.PSARequestFactory;
import com.sadiel.catcert.psa.ws.signature.InitSignDocumentAtPSADocument;
import com.sadiel.catcert.psa.ws.signature.InitSignDocumentAtPSAResponseDocument;
import com.sadiel.www.pdf.visiblesignature.v0_1.CertificateDataListType;
import com.sadiel.www.pdf.visiblesignature.v0_1.CertificateDataType;
import com.sadiel.www.pdf.visiblesignature.v0_1.RectangleInfoType;
import com.sadiel.www.pdf.visiblesignature.v0_1.VisibleSignatureDataType;
import com.sadiel.www.pdf.visiblesignature.v0_1.VisibleSignaturePosition;

import dss_directsign.profiles._0._1.psa.catcert.DocumentHashDocument.DocumentHash;
import dss_directsign.profiles._0._1.psa.catcert.DocumentOrDocumentHashType;
import dss_directsign.profiles._0._1.psa.catcert.DocumentType;
import dss_directsign.profiles._0._1.psa.catcert.Documents;
import dss_directsign.profiles._0._1.psa.catcert.InitSignDocumentAtPSARQSTDocument.InitSignDocumentAtPSARQST;
import dss_directsign.profiles._0._1.psa.catcert.MultiSignDocumentAtPSARSPNSDocument.MultiSignDocumentAtPSARSPNS;
import dss_directsign.profiles._0._1.psa.catcert.SignDocumentAtPSARSPNSDocument.SignDocumentAtPSARSPNS;
import dss_directsign.profiles._0._1.psa.catcert.SignedDocumentIdsDocument.SignedDocumentIds;


/**
 * Invoke psa signature service
 * @author suport tčcnic CATCert
 *
 */
public class InitSignDocumentAtPSASample {


	/**
	 * Main to test initSignDocumentAtPsa
	 * @param args
	 * @throws Exception 
	 */
	public static void main(String[] args) throws Exception {
		try{
			initSignDocumentAtPsa();
		} catch (Throwable e) {
			e.printStackTrace();
		}

	}


	/**
	 * Invoke initSignDocumentAtPsa
	 * @throws Exception
	 */
	public static SignDocumentAtPSARSPNS initSignDocumentAtPsa() throws Exception{



		//política de procediment
		String functionalProcedureId = "PP-0004";

		//localització (idioma)
		String locale = "ES";

		//certificat de signatura
		String certFilePath = System.getProperty("user.dir")+"/resource/test/signature/SIGN_SegellOrgan_Ajuntament_Exemple.cer";
		X509Certificate keySelector = Utils.getX509Certificate(certFilePath);

		//documents a signar
		String dataToSignFilePath = System.getProperty("user.dir")+"/resource/test/docs/prova.pdf";
		byte[] dataToSign = Utils.resourceAsBytes(dataToSignFilePath);
		byte[][] documents = new byte[1][dataToSign.length];
		documents[0] = dataToSign;

		//rol
		String role = null;

		//retorn d'informació
		boolean returnReport = true;
		boolean returnSignedDocument = true;
		boolean returnSignedDocumentId = true;

		//validació contra PSIS
		boolean psisValidation = false;

		//signature visible
		boolean showVisibleSignature = true;

		//configuració de la signatura visible
		VisibleSignatureDataType visibleSignData = VisibleSignatureDataType.Factory.newInstance();
		VisibleSignaturePosition visibleSignPosition = VisibleSignaturePosition.Factory.newInstance();
		//rectangle del camp de signatura
		RectangleInfoType rectangle = RectangleInfoType.Factory.newInstance();
		rectangle.setLowerLeftX(BigInteger.valueOf(100));
		rectangle.setLowerLeftY(BigInteger.valueOf(100));
		rectangle.setUpperRightX(BigInteger.valueOf(480));
		rectangle.setUpperRightY(BigInteger.valueOf(200));
		rectangle.setPageNumber("1");
		visibleSignPosition.setRectangleInfo(rectangle);
		visibleSignData.setVisibleSignaturePosition(visibleSignPosition);
		//data
		visibleSignData.setDate(true);
		//imatge
		visibleSignData.setImage(true);
		visibleSignData.setImageData(Utils.resourceAsBytes(System.getProperty("user.dir") + "/resource/test/imatges/sello.jpg"));
		//localització
		visibleSignData.setLocation(true);
		//raó
		visibleSignData.setReason(true);
		//camps del certificat
		CertificateDataListType certDataListType = CertificateDataListType.Factory.newInstance();
		com.sadiel.www.pdf.visiblesignature.v0_1.CertificateDataType.Enum[] certificateDataArray = new com.sadiel.www.pdf.visiblesignature.v0_1.CertificateDataType.Enum[7];
		certificateDataArray[0] = CertificateDataType.COUNTRY;
		certificateDataArray[1] = CertificateDataType.ORGANIZATION_NAME;
		certificateDataArray[2] = CertificateDataType.TITLE;
		certificateDataArray[3] = CertificateDataType.SURNAME;
		certificateDataArray[4] = CertificateDataType.GIVEN_NAME;
		certificateDataArray[5] = CertificateDataType.COMMON_NAME;
		certificateDataArray[6] = CertificateDataType.SERIAL_NUMBER;
		certDataListType.setCertificateDataArray(certificateDataArray);
		visibleSignData.setInfoText(certDataListType);

		// compromís
		String identifierTypeValue = "urn:catcert:compromisos:signatura:aprovo";
		String commitmentsFieldOfApplication = "Aprovació genčrica";
		String commitmentsSemantics = "Proof of origin indicates that the signer recognizes to have created, approved and sent the message";
		String oidTypeDescription = "Aprovació genčrica";

		Enum qualifierType = QualifierType.OID_AS_URN;

		//petició
		InitSignDocumentAtPSARQST request =  PSARequestFactory._().createInitSignDocumentAtPSA(
				functionalProcedureId, 
				documents, 
				role, 
				oidTypeDescription, 
				commitmentsSemantics, 
				commitmentsFieldOfApplication, 
				identifierTypeValue, 
				qualifierType, 
				returnReport, 
				returnSignedDocument, 
				returnSignedDocumentId, 
				showVisibleSignature, 
				visibleSignData, 
				psisValidation);

		String issuerName = Utils.getIssuerForPSARequest(keySelector);
		BigInteger serialNumber = keySelector.getSerialNumber();
		InitSignDocumentAtPSARQST[] requests = new InitSignDocumentAtPSARQST[1];
		requests[0] = request;
		InitSignDocumentAtPSADocument createMultiInitSignDocumentAtPSA = PSARequestFactory._().createMultiInitSignDocumentAtPSA(locale, issuerName, serialNumber, requests);

		SignatureServiceStub signService = PsaServices.getInstance().getSignatureServiceStub();	
		InitSignDocumentAtPSAResponseDocument psaResponse = signService.initSignDocumentAtPSA(createMultiInitSignDocumentAtPSA);
		MultiSignDocumentAtPSARSPNS multiSignDocumentAtPSARSPNS = psaResponse.getInitSignDocumentAtPSAResponse().getMultiSignDocumentAtPSARSPNS();

		//resposta
		SignDocumentAtPSARSPNS response = multiSignDocumentAtPSARSPNS.getSignDocumentAtPSARSPNSArray(0);

		// print response
		printResponse(response, returnReport, returnSignedDocumentId);

		// return response
		return response;

	}

	public static void printResponse(SignDocumentAtPSARSPNS response, boolean returnReport, boolean returnSignedDocument) throws Exception{

		//resultat de l'operació sol·licitada
		System.out.println("* Result:");
		Result result = response.getResult();
		String major = result.getResultMajor();
		String minor = result.getResultMinor();
		InternationalStringType message = result.getResultMessage();
		System.out.println("Major: "+major);
		System.out.println("Minor: "+minor);
		if(message!=null)
			System.out.println("Message: "+message.getStringValue());

		//identificador del context de signatura iniciat, necessari per les següents peticions associades al mateix context
		String procedureContextOid = response.getProcedureContextOID();
		System.out.println("* Procedure Context ID: "+procedureContextOid);

		//identificador del context de signatura
		String signatureActOid = response.getSignatureActOID();
		System.out.println("* Signature Act ID: "+signatureActOid);

		//report
		Documents reportsDocuments = response.getReportsDocuments();
		if(returnReport){
			if(reportsDocuments!=null && (reportsDocuments.getDocumentArray()!=null)){
				System.out.println("* Report:");
				DocumentType[] documentArray = reportsDocuments.getDocumentArray();
				for(int i=0;i<documentArray.length;i++){
					System.out.println("Report file name: "+documentArray[i].getFilename());
					System.out.println("Report ID: "+documentArray[i].getID());
					String reportFilePath = System.getProperty("user.dir")+"/resource/reports/"+documentArray[i].getFilename() + "1.pdf";
					byte[] data = documentArray[i].getData();
					Utils.writeDataToFile(reportFilePath, data);
				}
			}
		}

		//document signat
		DocumentOrDocumentHashType outDocs = response.getOutputDocuments();
		if(outDocs!=null){
			DocumentType[] outDocsArray = outDocs.getDocumentArray();
			DocumentHash[] outDocsHashArray = outDocs.getDocumentHashArray();
			System.out.println("* Document:");
			if(outDocsArray!=null && outDocsArray.length != 0){
				DocumentType doc = outDocsArray[0];
				System.out.println("Doc filename: "+doc.getFilename());
				System.out.println("Doc ID: "+doc.getID());
				String reportFilePath = System.getProperty("user.dir")+"/resource/reports/"+doc.getFilename() + "signat.pdf";
				Utils.writeDataToFile(reportFilePath, doc.getData());
			} else if(outDocsHashArray!=null && outDocsHashArray.length != 0){
				DocumentHash doc = outDocsHashArray[0];
				System.out.println("Doc Hash ID: "+doc.getID());
				System.out.println("Doc Hash digest: "+doc.getDigestValue());
				System.out.println("Doc Hash algorithm: "+doc.getDigestMethod().getAlgorithm());
			}
		}

		//id del document signat
		SignedDocumentIds signedDocsIds = response.getSignedDocumentIds();
		if(returnSignedDocument){
			System.out.println("* Signed Document:");
			if(signedDocsIds!=null){
				String[] signedDocsArray = signedDocsIds.getSignedDocumentIdArray();
				if(signedDocsArray!=null){
					for(int i=0;i<signedDocsArray.length;i++){
						System.out.println("Doc ID: "+signedDocsArray[i]);
					}
				}
			}
		}
	}

}
