package com.izenpe.zain.cliente.xades;

import org.apache.axis.encoding.Base64;

import com.izenpe.zain.client.ZainConfig;
import com.izenpe.zain.cliente.util.Constantes;
import com.izenpe.zain.cliente.util.Propiedades;
import com.izenpe.zain.cliente.util.ZainUtil;
import com.safelayer.trustedx.client.smartwrapper.Constants;
import com.safelayer.trustedx.client.smartwrapper.SmartVerifyRequest;
import com.safelayer.trustedx.client.smartwrapper.SmartVerifyResponse;

public class ActualizacionFirmaXML {
	// Nombre del fichero a ser actualizado mediante la firma XML.
	private static final String fileName = "DemoSignedEnvelopingTS.xml";

	public static void main(String[] args) {
		try {
			// Asignación de la configuración de forma programática
			ZainConfig.setCurrent(Propiedades.ZAIN_CONFIG);

			/*
			 * Se crea la petición a través de la URL definida en ZAIN_ENDPOINT.
			 * 
			 * SmartVerifyRequest.Service.DR para que la petición de
			 * verificación de firma también sea una petición de actualización
			 * de firma (dirigida al servicio DR de TrustedX).
			 * 
			 * El valor por defecto de este parámetro es
			 * SmartVerifyRequest.Service.DSV para solicitar sólo una
			 * verificación de firma al servicio DSV.
			 */
			SmartVerifyRequest smartVerifyReq = new SmartVerifyRequest(Propiedades.ZAIN_ENDPOINT,
					SmartVerifyRequest.Service.DR);

			// Se establece el perfil No Repudio en la petición de Verificación
			// de firma.
			smartVerifyReq.setProfile(Constants.Profile.NONREP);

			/*
			 * Se establece el idioma de la petición en español. 2
			 * posibilidades: 1. Español: 'es' 2. Inglés: 'en'
			 */
			smartVerifyReq.setLanguage("es");

			/*
			 * Se solicita en la petición de Verificación que se añadan a la
			 * respuesta los valores de los certificados.
			 */
			smartVerifyReq.setAddCertificateValues(Constants.AddValues.BINARY);

			/*
			 * Se solicita en la petición de Verificación que se añadan a la
			 * respuesta la información de revocación de los certificados.
			 */
			smartVerifyReq.setAddRevocationValues(Constants.AddValues.BINARY);

			/*
			 * Se solicita en la petición de Verificación que se añadan los
			 * valores del Sello de Tiempo.
			 */
			smartVerifyReq.setAddTimeStampValues(Constants.AddValues.BINARY);

			/*
			 * True para que la respuesta incluya el formato de la firma (e.g.
			 * BES, ES-T). La invocación de método es indispensable para
			 * consultar el formato de la respuesta con getSignatureForm.
			 */
			smartVerifyReq.setAddSignatureForm(true);

			/*
			 * Constants.SignatureFormat.ES_T para solicitar un sello de tiempo
			 * en la firma. Con el valor Constants.SignatureFormat.ES_A, la
			 * respuesta añadiría información sobre la validez del certificado.
			 */
			smartVerifyReq.setReturnUpdatedSignature(Constants.SignatureFormat.ES_A);

			// Datos a verificar.
			smartVerifyReq.setInputXmlBase64(Base64.encode(ZainUtil.readBinaryFile("data/output/" + fileName)));

			// Envío de la petición.
			SmartVerifyResponse smartVerifyResp = smartVerifyReq.send();

			/*
			 * 0 para consultar la primera y única firma. Sin una invocación
			 * previa de setAddSignatureForm(true), este método devuelve null.
			 */
			System.out.println("Verificando firma con formato: " + smartVerifyResp.getSignature(0).getSignatureForm());

			// Se comprueba la validez de la respuesta de Actualización de firma
			// XML.
			if (Constantes.RMAJOR_SUCCESS.equals((smartVerifyResp.getResultMajor()))
					&& Constantes.RMINOR_SUCCESS.equals(smartVerifyResp.getResultMinor())) {
				String signXML = smartVerifyResp.getDocumentWithSignatureXml();
				String destFilename = "data/output/" + fileName.substring(0, fileName.lastIndexOf(".")) + "Archive.xml";
				ZainUtil.writeBinaryFile(destFilename, signXML.getBytes());
				System.out.println("La firma ha sido actualizada con éxito.");
			} else {
				System.out.println("La actualización de la firma contiene errores: "
						+ smartVerifyResp.getResultMessage());
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}