package com.ejie.ad74a.ws.client.dokusi.service;

import java.io.ByteArrayInputStream;
import java.io.UnsupportedEncodingException;
import java.rmi.UnmarshalException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;

import org.apache.commons.lang.exception.ExceptionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.ejie.ad74a.constantes.Constantes;
import com.ejie.ad74a.exceptions.ManagerErrors;
import com.ejie.ad74a.model.DocumentoPapel0;
import com.ejie.ad74a.model.DocumentosTarea;
import com.ejie.ad74a.model.Expedientes;
import com.ejie.ad74a.model.FirmaInfo;
import com.ejie.ad74a.util.comun.UtilSeguridad;
import com.ejie.ad74a.util.comun.UtilTokenXlnets;
import com.ejie.ad74a.util.comun.Utilidades;
import com.ejie.ad74a.ws.client.dokusi.document.T65BIFSDWSClasePort;
import com.ejie.ad74a.ws.client.dokusi.gestDocumental.T65AuditUser;
import com.ejie.ad74a.ws.client.dokusi.gestDocumental.T65BFsdJaxbInterface;
import com.ejie.ad74a.ws.client.dokusi.gestDocumental.T65Content;
import com.ejie.ad74a.ws.client.dokusi.gestDocumental.T65DocumentId;
import com.ejie.ad74a.ws.client.dokusi.model.documentT65B.T65BAttributeListType;
import com.ejie.ad74a.ws.client.dokusi.model.documentT65B.T65BContentType;
import com.ejie.ad74a.ws.client.dokusi.model.documentT65B.T65BDocumentIDType;
import com.ejie.ad74a.ws.client.dokusi.model.documentT65B.T65BDocumentType;
import com.ejie.ad74a.ws.client.dokusi.model.documentT65B.T65BFormatType;
import com.ejie.ad74a.ws.client.dokusi.model.documentT65B.T65BStringListType;
import com.ejie.ad74a.ws.client.dokusi.model.papel0.Metadato;
import com.ejie.ad74a.ws.client.dokusi.model.signatureList.SignatureInfoType;
import com.ejie.ad74a.ws.client.dokusi.model.signatureList.SignatureList;
import com.ejie.ad74a.ws.client.dokusi.model.signatureList.SignatureType;
import com.ejie.ad74a.ws.client.dokusi.model.signatures.SignatureCountList;
import com.ejie.ad74a.ws.client.firmaX43fn.EjgvDocument;
import com.ejie.ad74a.ws.client.platea.dossierDokusi.X98DossierWebService;
import com.ejie.ad74a.ws.client.platea.service.PlateaUtils;
import com.ejie.dossierDokusi.xml.Root;
import com.ejie.t65.jaxb.beans.fsd.DocumentIDListDocument;
import com.ejie.t65.jaxb.beans.fsd.T65AttributeType;
import com.ejie.t65.jaxb.beans.fsd.T65ConditionListType;
import com.ejie.t65.jaxb.beans.fsd.T65ConditionType;
import com.ejie.t65.jaxb.beans.fsd.T65ContentListType;
import com.ejie.t65.jaxb.beans.fsd.T65ContentType;
import com.ejie.t65.jaxb.beans.fsd.T65DocumentIDListType;
import com.ejie.t65.jaxb.beans.fsd.T65DocumentIDType;
import com.ejie.t65.jaxb.beans.fsd.T65DocumentListType;
import com.ejie.t65.jaxb.beans.fsd.T65DocumentType;
import com.ejie.t65.jaxb.beans.fsd.T65StringListType;

@Service(value = "DokusiService")
public class DokusiServiceImpl implements DokusiService {

	/**
	 * Final static logger.
	 */
	private static final Logger logger = LoggerFactory.getLogger(DokusiServiceImpl.class);

	@Autowired
	private T65BFsdJaxbInterface t65BFsdJaxbInterface;

	@Autowired
	private T65BIFSDWSClasePort t65BFSDWSClasePort;

	@Autowired
	private FirmaService firmaService;

	@Autowired
	private Properties appConfiguration;

	@Autowired
	private X98DossierWebService x98DossierWebService;

	private static final String GENERIC_OBJECT_NAME = "object_name";

	private static final String INTERN_NATURALEZA = "ejgv_naturaleza";

	private static final String GENERIC_CREATION_DATE = "r_creation_date";

	private static final String NUM_TITULARAPORT = "ejgv_num_titularoaport";

	/**
	 * Clase que adaptara los servicios de Dokusi a nuestro sistema
	 */
	private DokusiServiceImpl() {
		super();
	}

	/**
	 * INICIO TOOLKIT X43KWebService com.ejie.ad74a.ws.client.platea.toolkit
	 **/

	@Override
	public T65Content retrieveDocumentOrSuperLocator(String oidDocument) {
		DokusiServiceImpl.logger
				.info("[DokusiServiceImpl] - retrieveDocumentOrSuperLocator oidDocument: " + oidDocument);
		T65Content t65Content = null;
		try {
			T65AuditUser t65AuditUser = new T65AuditUser();
			t65AuditUser.setDni(Constantes.COD_APLICACION);
			t65AuditUser.setName(Constantes.COD_APLICACION);
			t65AuditUser.setUser(Constantes.COD_APLICACION);
			T65DocumentId t65DocumentID = new T65DocumentId();
			t65DocumentID.setId(oidDocument);
			t65Content = new T65Content();
			String rutaPif = this.appConfiguration.getProperty("webservice.dokusi.pif.dir");
			t65Content.setPifId(rutaPif);

			t65Content = this.t65BFsdJaxbInterface.retrieveDocumentOrSuperLocator(t65AuditUser, t65DocumentID,
					t65Content);
		} catch (Exception e) {
			ManagerErrors.manageException(e,
					"Error al recuperar la ruta pif del documento: " + ExceptionUtils.getStackTrace(e));
		}
		DokusiServiceImpl.logger
				.info("[DokusiServiceImpl] - retrieveDocumentOrSuperLocator Fin: " + t65Content.getPifId());
		return t65Content;
	}

	public Map<String, Integer> retrieveDocumentsSignaturesCount(String[] dokusiIDs, String procedureID,
			String auditUser) {
		DokusiServiceImpl.logger.info("[DokusiServiceImpl] - retrieveDocumentsSignaturesCount Inicio");
		Map<String, Integer> result = new HashMap<String, Integer>();
		String resultDokusi = "";
		try {
			com.ejie.ad74a.ws.client.platea.expedienteElectronico.AExtensionPoint ep = new com.ejie.ad74a.ws.client.platea.expedienteElectronico.AExtensionPoint();

			resultDokusi = this.t65BFSDWSClasePort.retrieveDocumentsSignaturesCount(
					UtilTokenXlnets.getTokenStringXLNets(Constantes.COD_APLICACION), auditUser,
					this.generateT65bDocumentIDArray(dokusiIDs, null), null);

			result = this.unmarshalSignatureCountMap(resultDokusi);

			DokusiServiceImpl.logger.info("[DokusiServiceImpl] - retrieveDocumentsSignaturesCount Fin");
		} catch (Throwable e) {
			ManagerErrors.manageException(e, "Error al recuperar las firmas de Dokusi");
		}
		return result;
	}

	private String generateT65bDocumentIDArray(String[] docIDs, String[] versiones) {
		String rdo = null;
		DocumentIDListDocument documentIDArrayDoc = DocumentIDListDocument.Factory.newInstance();
		T65DocumentIDListType documentIDArray = documentIDArrayDoc.addNewDocumentIDList();
		if (docIDs != null) {
			for (int i = 0; i < docIDs.length; i++) {
				if (null != docIDs[i] && docIDs[i].length() > 0) {
					T65DocumentIDType documentID = documentIDArray.addNewDocumentID();
					documentID.setId(docIDs[i]);
					if (versiones != null && i < versiones.length) {
						documentID.setVersion(versiones[i]);
					}
				}
			}
			rdo = documentIDArrayDoc.xmlText();
			// String cadena = " xmlns:fsd=\"" + "com/ejie/t65/jaxb/beans/fsd" + "\"";
			// rdo = rdo.replaceAll(cadena, "");
			// rdo = rdo.replaceAll("fsd:", "");
			// rdo = rdo.replaceAll("<xml-fragment>", "<documentIDArray><documentIDList>");
			// rdo = rdo.replaceAll("</xml-fragment>",
			// "</documentIDArray></documentIDList>");
			return rdo;
		}
		return rdo;
	}

	private Map<String, Integer> unmarshalSignatureCountMap(String xml) throws UnmarshalException {
		JAXBContext jaxbContext;
		Map<String, Integer> numFirmas = new HashMap<String, Integer>();
		try {

			xml = xml.replaceAll("<signatureCountList>", "<signatureCountList xmlns=\\\"com/ejie/dokusi/xml\\\">");
			jaxbContext = JAXBContext.newInstance(SignatureCountList.class);

			Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
			SignatureCountList signCountList = (SignatureCountList) jaxbUnmarshaller
					.unmarshal(new ByteArrayInputStream(xml.getBytes("UTF-8")));
			for (com.ejie.ad74a.ws.client.dokusi.model.signatures.SignatureCountType signCountType : signCountList
					.getSignatureCount()) {
				numFirmas.put(signCountType.getDocumentId().getId(),
						Integer.parseInt(signCountType.getNumSignatures()));

			}
			return numFirmas;

		} catch (JAXBException e) {
			throw new UnmarshalException("Error de JAXB al traducir el XML", e);
		} catch (UnsupportedEncodingException e) {
			throw new UnmarshalException("Error de codificacion al leer el XML", e);
		}
	}

	public T65DocumentListType retrieveDocumentsFirmantes(String[] docuOIDArray) {
		String[] keysList = new String[2];
		keysList[0] = Constantes.INTERN_ID_FIRMANTES;
		keysList[1] = Constantes.INTERN_NOM_FIRMANTES;
		return this.retrieveDocuments(docuOIDArray, null, keysList);
	}

	public T65DocumentListType retrieveDocuments(String[] strOid, T65ContentListType contents, String[] keysList) {
		DokusiServiceImpl.logger.info("En DokusiServiceImpl.retrieveDocuments");
		try {

			String strToken = UtilTokenXlnets.getTokenStringXLNets(com.ejie.ad74a.constantes.Constantes.COD_APLICACION);

			String strAuditUser = UtilSeguridad.getAuditUser();
			// Parsea objetos a cadenas
			String paramStrContent = DokusiXMLBeanParserConverter.parseToStringContentList(contents);
			String paramStrOid = DokusiXMLBeanParserConverter.parseToStringDocumentIDList(strOid);
			String paramStrKeysList = DokusiXMLBeanParserConverter.generateT65BKeysForMuchDocs(strOid.length, keysList);

			// Llama servicio (segun documento UDA, con url de properties)
			String strXmlResp = this.t65BFSDWSClasePort.retrieveDocuments(strToken, strAuditUser, paramStrOid,
					paramStrKeysList, paramStrContent);
			T65DocumentListType objResp = DokusiXMLBeanParserConverter.parseToT65BDocumentList(strXmlResp);

			DokusiServiceImpl.logger.info("Fin retrieveDocuments");
			return objResp;
		} catch (Exception e) {
			DokusiServiceImpl.logger.error("Excepcion DokusiServiceImpl.retrieveDocuments", e);
			return null;
		}
	}

	public boolean tramitateDocument(com.ejie.ad74a.ws.client.dokusi.model.papel0.Documento documento) {
		DokusiServiceImpl.logger.info("En DokusiServiceImpl.tramitateDocument");
		boolean resultado = false;
		try {

			String strToken = UtilTokenXlnets.getTokenStringXLNets(com.ejie.ad74a.constantes.Constantes.COD_APLICACION);
			String strAuditUser = UtilSeguridad.getAuditUser();

			String documentID = DokusiXMLBeanParserConverter.crearXMLdocumentID(documento.getOidDokusi());

			String attributeList = DokusiXMLBeanParserConverter.crearXMLAttributeListRetramitar(documento);

			resultado = t65BFSDWSClasePort.tramitateDocument(strToken, strAuditUser, documentID,
					documento.getNewRoleId(), attributeList);

		} catch (Exception e) {
			DokusiServiceImpl.logger.error("Excepcion DokusiServiceImpl.tramitateDocument", e);
			ManagerErrors.manageException(e, "Error en tramitateDocument");
		}
		return resultado;
	}

	public boolean reTramitateDocument(com.ejie.ad74a.ws.client.dokusi.model.papel0.Documento documento) {
		DokusiServiceImpl.logger.info("En DokusiServiceImpl.reTramitateDocument");
		boolean resultado = false;
		try {

			String strToken = UtilTokenXlnets.getTokenStringXLNets(com.ejie.ad74a.constantes.Constantes.COD_APLICACION);
			String strAuditUser = UtilSeguridad.getAuditUser();

			String documentID = DokusiXMLBeanParserConverter.crearXMLdocumentID(documento.getOidDokusi());

			String attributeList = DokusiXMLBeanParserConverter.crearXMLAttributeListRetramitar(documento);

			resultado = t65BFSDWSClasePort.retramitateDocument(strToken, strAuditUser, documentID,
					documento.getNewRoleId(), attributeList);

		} catch (Exception e) {
			DokusiServiceImpl.logger.error("Excepcion DokusiServiceImpl.reTramitateDocument", e);
			ManagerErrors.manageException(e, "Error en reTramitateDocument");
		}
		return resultado;
	}

	/**
	 * Metodo que descarga el documento de DOKUSI
	 * 
	 * @param documento Objeto con los atributos necesarios para registrar el
	 *                  documento en dokusi
	 * 
	 * @return Documento.
	 * @throws Exception
	 */
	public T65DocumentType descargarDocumentoDokusi(DocumentoPapel0 docPapel) {
		DokusiServiceImpl.logger.info("DokusiServiceImpl.descargarDocumentoDokusi - Inicio");
		// com.ejie.ad74a.ws.client.dokusi.model.papel0.Documento documentoDescargado =
		// null;
		T65DocumentType t65BDocumentType = null;
		try {

			// recuperamos los datos de la bandeja

			String tokenSesion = UtilTokenXlnets
					.getTokenStringXLNets(com.ejie.ad74a.constantes.Constantes.COD_APLICACION);
			String strAuditUser = UtilSeguridad.getAuditUser();

			com.ejie.ad74a.ws.client.dokusi.model.papel0.Documento documento = new com.ejie.ad74a.ws.client.dokusi.model.papel0.Documento();
			documento.setOidDokusi(docPapel.getOidDocumento13());
			com.ejie.ad74a.ws.client.dokusi.model.papel0.User user = new com.ejie.ad74a.ws.client.dokusi.model.papel0.User();
			String[] datosUser = docPapel.getBandejaPapel0().getRemitente12().split("-");
			if (datosUser.length > 1) {
				user.setDni(datosUser[1].trim()); // PARA PROBAR. No debería ser
			}
			user.setNombre(datosUser[0].trim());
			documento.setUser(user);

			List<Metadato> metadatos = getMetadatos(documento);

			documento.setMetadatos(metadatos);

			String documentID = DokusiXMLBeanParserConverter.crearXMLdocumentID(documento.getOidDokusi());

			com.ejie.ad74a.ws.client.dokusi.model.papel0.Formato formato = this
					.recuperarFormatosDocumentosDokusi(documento);

			String formatoName = formato.getName();
			String keysList = DokusiXMLBeanParserConverter.crearXMLReturnedAttributeKeysList(documento.getMetadatos());

			String rutaPif = this.appConfiguration.getProperty("webservice.dokusi.pif.dir");
			String content = DokusiXMLBeanParserConverter.crearXMLContentName(formatoName, rutaPif);

			String resultado = t65BFSDWSClasePort.retrieveDocument(tokenSesion, strAuditUser, documentID, keysList,
					content);
			DokusiServiceImpl.logger.info("DokusiServiceImpl.descargarDocumentoDokusi - Return: " + resultado);

			t65BDocumentType = DokusiXMLBeanParserConverter.transformToDocumentType(resultado);
			// documentoDescargado =
			// DokusiXMLBeanParserConverter.transformDescargarDocumentoDokusi(resultado);

		} catch (Exception e) {
			ManagerErrors.manageException(e, "Error al descargar el documento descargarDocumentoDokusi");
		}
		return t65BDocumentType;
	}

	/**
	 * Metodo que recupera los formatos de un documento de DOKUSI
	 * 
	 * @param documento Objeto con los atributos necesarios para recuperar el
	 *                  formato del documento en dokusi
	 * 
	 * @return Formato.
	 */
	public com.ejie.ad74a.ws.client.dokusi.model.papel0.Formato recuperarFormatosDocumentosDokusi(
			com.ejie.ad74a.ws.client.dokusi.model.papel0.Documento documento) {
		DokusiServiceImpl.logger.info("DokusiServiceImpl.recuperarFormatosDocumentosDokusi - Inicio");
		com.ejie.ad74a.ws.client.dokusi.model.papel0.Formato formato = null;
		try {
			String tokenSesion = UtilTokenXlnets
					.getTokenStringXLNets(com.ejie.ad74a.constantes.Constantes.COD_APLICACION);
			String strAuditUser = UtilSeguridad.getAuditUser();

			String name = UtilSeguridad.getUsuarioConectado().getName();
			String nif = UtilSeguridad.getUsuarioConectado().getNif();

			// String audit = "11111111R#FERNANDEZ ARCHIDUQUE, JUAN";
			String audit = documento.getUser().getDni() + "#" + documento.getUser().getNombre();
			String documentID = DokusiXMLBeanParserConverter.crearXMLdocumentID(documento.getOidDokusi());

			String resultado = t65BFSDWSClasePort.retrieveDocumentFormats(tokenSesion, audit, documentID);

			DokusiServiceImpl.logger.info("DokusiServiceImpl.recuperarFormatosDocumentosDokusi - Return: " + resultado);

			formato = DokusiXMLBeanParserConverter.transformRecuperarFormatosDocumentosDokusi(resultado);

		} catch (Exception e) {
			ManagerErrors.manageException(e, "Error en recuperarFormatosDocumentosDokusi");
		}
		return formato;
	}

	/**
	 * Almacena un documento en Dokusi
	 * 
	 * @param token          String
	 * @param auditUser      String
	 * @param doc            ExpDocTramite
	 * @param logTramitacion LogTramitacion
	 * 
	 * @return T65BDocumentIDType
	 * 
	 * @throws DokusiException     excepciÃ³n lanzada por Dokusi
	 * @throws AB37AParseException excepciÃ³n al parsear la respuesta de Dokusi
	 */
	public T65BDocumentIDType almacenarDocumento(String auditUser, DocumentosTarea doc, Expedientes expediente)
			throws Exception {

		DokusiServiceImpl.logger.info("DokusiServiceImpl.almacenarDocumento - Inicio");

		String token = UtilTokenXlnets.getTokenStringXLNets(Constantes.COD_APLICACION);

		T65BContentType t65bContentType = DokusiXMLBeanParserConverter.construirT65BContentType(doc);
		T65BAttributeListType t65bAttributeListType = DokusiXMLBeanParserConverter.generarMetadatosBasicos(doc,
				expediente);

		String content = "";
		if (t65bContentType != null) {
			content = DokusiXMLBeanParserConverter.getT65BContentTypeAsString(t65bContentType);
		}

		DokusiServiceImpl.logger.info("DokusiServiceImpl.almacenarDocumento content: " + content);

		String attributeList = "";
		if (t65bAttributeListType != null) {
			attributeList = DokusiXMLBeanParserConverter.getT65BAttributeListTypeAsString(t65bAttributeListType);
		}

		String response = null;
		try {

			String roleIdDokusi = "";
			String[] tiposdoc = doc.getMaestroTiposDoc().getRoleid36().split("\\.");
			if (Arrays.asList(tiposdoc).contains("0")) {
				roleIdDokusi = tiposdoc[Arrays.asList(tiposdoc).indexOf("0") - 1];
			} else {
				roleIdDokusi = tiposdoc[tiposdoc.length - 2];
			}

			// TODO El roleID es el tipo de dokusi¿?¿?¿?
			response = t65BFSDWSClasePort.storeDocument(token, auditUser, content, roleIdDokusi, attributeList);
		} catch (Exception e) {
			ManagerErrors.manageException(e, "Error en la llamada a storeDocument");
		}

		T65BDocumentIDType t65bDocumentIDType = DokusiXMLBeanParserConverter
				.getDokusiResponseAsT65BDocumentIDType(response);

		return t65bDocumentIDType;
	}

	/**
	 * Metodo usado para recuperar el documento despues de mandarlo a localizar
	 * 
	 * @param auditUser
	 * @param doc
	 * @param t65bStringListType
	 * @return
	 * @throws Exception
	 */
	public T65BDocumentType recuperarDocumentoLocator(String auditUser, DocumentosTarea doc,
			T65BStringListType t65bStringListType) throws Exception {

		DokusiServiceImpl.logger.info("DokusiServiceImpl.recuperarDocumento - Inicio");

		T65BDocumentIDType t65bDocumentIDType = DokusiXMLBeanParserConverter
				.construirT65BDocumentIDType(doc.getOiddokusi18(), null);
		T65BContentType t65bContentType = new T65BContentType();

		String documentID = DokusiXMLBeanParserConverter.getT65BDocumentIDTypeAsString(t65bDocumentIDType);
		String keysList = DokusiXMLBeanParserConverter.getT65BStringListTypeAsString(t65bStringListType);

		String response = null;
		try {
			DokusiServiceImpl.logger.info("Se va a recuperar de Dokusi el formato del documento con OID {} y verson {}",
					t65bDocumentIDType.getId(), t65bDocumentIDType.getVersion());

			response = this.t65BFSDWSClasePort.retrieveDocumentFormats(
					UtilTokenXlnets.getTokenStringXLNets(Constantes.COD_APLICACION), auditUser, documentID);

			List<T65BFormatType> listaFormat = DokusiXMLBeanParserConverter
					.getDokusiResponseAsT65BFormatListType(response).getFormat();
			T65BFormatType format = null;
			for (T65BFormatType t65bFormatType : listaFormat) {
				format = t65bFormatType;
				if ("pdf".equals(t65bFormatType.getExtension())) {
					break;
				}
			}

			t65bContentType.setFormat(format);

			// dejamos el documento en un zona pif nuestra
			// movemos el documento a una ruta nuestra
			String pathDestino = this.appConfiguration.getProperty("ruta.pif.platea")
					+ doc.getRutapif18().substring(doc.getRutapif18().lastIndexOf("/") + 1);

			t65bContentType.setPifId(pathDestino);
			// t65bContentType.setPifId(doc.getRutapif18());

			String content = DokusiXMLBeanParserConverter.getT65BContentTypeAsString(t65bContentType);

			DokusiServiceImpl.logger.info("Se va a recuperar de Dokusi el documento con OID {} y versiÃ³n {}",
					t65bDocumentIDType.getId(), t65bDocumentIDType.getVersion());

			response = this.t65BFSDWSClasePort.retrieveDocument(
					UtilTokenXlnets.getTokenStringXLNets(Constantes.COD_APLICACION), auditUser, documentID, keysList,
					content);
		} catch (Exception e) {
			DokusiServiceImpl.logger.error("Error en la llamada a retrieveDocument de Dokusi", e);
			ManagerErrors.manageException(e, "Error en la llamada a retrieveDocument de Dokusi");
		}

		if (response != null) {
			T65BDocumentType t65bDocumentType = DokusiXMLBeanParserConverter
					.getDokusiResponseAsT65BDocumentType(response);

			DokusiServiceImpl.logger.info("Documento recuperado de Dokusi con OID {} versiÃ³n {}",
					t65bDocumentType.getDocumentID().getId(), t65bDocumentType.getDocumentID().getVersion());

			return t65bDocumentType;
		} else {
			DokusiServiceImpl.logger.info("La respuesta de retrieveDocument de Dokusi es null");
			ManagerErrors.manageError("La respuesta de retrieveDocument de Dokusi es null");
		}
		return null;
	}

	// /**
	// * AÃ±ade una firma a un documento de Dokusi. Si Dokusi devuelve false se
	// lanza
	// * una excepciÃ³n. Por eso no es necesario devolver nada, es void.
	// *
	// * @param token String
	// * @param auditUser String
	// * @param t65bDocumentIDType T65BDocumentIDType
	// * @param t65bSignatureListType T65BSignatureListType
	// *
	// * @throws DokusiException excepciÃ³n lanzada por Dokusi
	// */
	// public void anadirFirma(String auditUser, T65BDocumentIDType
	// t65bDocumentIDType,
	// T65BSignatureListType t65bSignatureListType, String signature) throws
	// Exception {
	//
	// DokusiServiceImpl.logger.info("DokusiServiceImpl.anadirFirma - Inicio");
	//
	// String token =
	// UtilTokenXlnets.getTokenStringXLNets(Constantes.COD_APLICACION);
	//
	// String documentID =
	// DokusiXMLBeanParserConverter.getT65BDocumentIDTypeAsString(t65bDocumentIDType);
	//
	// String signatures =
	// DokusiXMLBeanParserConverter.getT65BSignatureListTypeAsString(t65bSignatureListType);
	//
	// try {
	// DokusiServiceImpl.logger
	// .info("DokusiServiceImpl.anadirFirma - Anyadimos firma al documento de dokusi
	// con Oid: "
	// + t65bDocumentIDType.getId() + " y version: " +
	// t65bDocumentIDType.getVersion());
	//
	// byte[] bytes = null;
	// if (null != signature) {
	// bytes = UtilidadesXML.decode(signature);
	// }
	// InputStream myInputStream = new ByteArrayInputStream(bytes);
	//
	// String rutaPifDokusi =
	// this.appConfiguration.getProperty("webservice.dokusi.pif.dir");
	//
	// String pathTo = rutaPifDokusi.concat("documentoFirmado.pdf");
	// String rutaPif = Ad74aPIFws.getInstance().uploadDocument(myInputStream,
	// pathTo, false);
	//
	// this.t65BFSDWSClasePort.addPadesSignaturesToDocument(token, auditUser,
	// documentID,
	// signatures, rutaPif);
	//
	// DokusiServiceImpl.logger
	// .info("DokusiServiceImpl.anadirFirma - Anyadimos firma al documento de dokusi
	// con Oid Final
	// ");
	// } catch (Exception e) {
	// DokusiServiceImpl.logger.info("La respuesta de addSignaturesToDocument de
	// Dokusi es null");
	// ManagerErrors.manageException(e, "La respuesta de addSignaturesToDocument de
	// Dokusi es
	// null");
	//
	// }
	// }

	/**
	 * Anyade localizador de forma asincrona a un documento de dokusi
	 * 
	 * @param auditUser
	 * @param oid
	 * @param versionar
	 * @param reducir
	 * @param logTramitacion
	 * @return
	 * @throws DokusiException
	 */
	public String anadirLocalizadorQR(String auditUser, String oid, boolean versionar, String reducir)
			throws Exception {

		DokusiServiceImpl.logger.info("DokusiServiceImpl.anadirLocalizadorQR - Inicio");

		String token = UtilTokenXlnets.getTokenStringXLNets(Constantes.COD_APLICACION);

		T65BDocumentIDType t65bDocumentIDType = DokusiXMLBeanParserConverter.construirT65BDocumentIDType(oid, null);

		String documentID = DokusiXMLBeanParserConverter.getT65BDocumentIDTypeAsString(t65bDocumentIDType);

		String response = null;
		try {

			response = this.t65BFSDWSClasePort.addLocatorToDocumentQR(token, auditUser, documentID, versionar, reducir,
					null);

			DokusiServiceImpl.logger.info("DokusiServiceImpl.anadirLocalizadorQR - Resultado: " + response);

			return response;
		} catch (Exception e) {
			DokusiServiceImpl.logger.info("Error en la llamada a addLocatorToDocumentQR");
			ManagerErrors.manageException(e, "Error en la llamada a addLocatorToDocumentQR");
		}
		return response;
	}

	public String firmarDocumentoPades(DocumentosTarea documento) throws Exception {

		DokusiServiceImpl.logger.info("DokusiServiceImpl.firmarDocumentoPades - Inicio");

		String auditUser = UtilSeguridad.getAuditUser();

		T65BDocumentIDType t65bDocumentIDType = DokusiXMLBeanParserConverter
				.construirT65BDocumentIDType(documento.getOiddokusi18(), null);

		// T65BFormatType t65bFormatType = new T65BFormatType();
		// t65bFormatType.setExtension("pdf");
		// t65bFormatType.setMimeType("application/pdf");
		// t65bFormatType.setName("pdfa");
		// t65bFormatType.setDescription("Description");
		//
		// T65BContentType t65bContentType = new T65BContentType();
		// t65bContentType.setFormat(t65bFormatType);

		T65BStringListType t65bStringListType = new T65BStringListType();

		String response = null;
		try {

			T65BDocumentType document = this.recuperarDocumentoLocator(auditUser, documento, t65bStringListType);

			EjgvDocument firma = this.firmaService.crearFirma(document);

			response = this.firmaService.anyadirFirma(firma, t65bDocumentIDType, auditUser);

			DokusiServiceImpl.logger.info("DokusiServiceImpl.firmarDocumentoPades - Resultado: " + response);

			return response;
		} catch (Exception e) {
			DokusiServiceImpl.logger.info("Error en la llamada a firmarDocumentoPades");
			ManagerErrors.manageException(e, "Error en la llamada a firmarDocumentoPades");
		}
		return response;
	}

	private List<Metadato> getMetadatos(com.ejie.ad74a.ws.client.dokusi.model.papel0.Documento documento) {
		List<Metadato> metadatos = documento.getMetadatos();
		if (metadatos == null) {
			metadatos = new ArrayList<Metadato>();
		}
		Metadato metadato = new Metadato();
		metadato.setNombre("object_name");
		metadatos.add(metadato);

		metadato = new Metadato();
		metadato.setNombre("title");
		metadatos.add(metadato);

		metadato = new Metadato();
		metadato.setNombre("ejgv_serie");
		metadatos.add(metadato);

		metadato = new Metadato();
		metadato.setNombre("ejgv_origen");
		metadatos.add(metadato);

		metadato = new Metadato();
		metadato.setNombre("i_chronicle_id");
		metadatos.add(metadato);

		metadato = new Metadato();
		metadato.setNombre("r_version_label");
		metadatos.add(metadato);

		metadato = new Metadato();
		metadato.setNombre("subject");
		metadatos.add(metadato);

		metadato = new Metadato();
		metadato.setNombre("keywords");
		metadatos.add(metadato);

		metadato = new Metadato();
		metadato.setNombre("authors");
		metadatos.add(metadato);

		metadato = new Metadato();
		metadato.setNombre("r_creation_date");
		metadatos.add(metadato);

		metadato = new Metadato();
		metadato.setNombre("r_modify_date");
		metadatos.add(metadato);

		metadato = new Metadato();
		metadato.setNombre("r_object_type");
		metadatos.add(metadato);

		metadato = new Metadato();
		metadato.setNombre("acl_name");
		metadatos.add(metadato);

		metadato = new Metadato();
		metadato.setNombre("owner_name");
		metadatos.add(metadato);

		metadato = new Metadato();
		metadato.setNombre("ejgv_entrada_salida");
		metadatos.add(metadato);

		metadato = new Metadato();
		metadato.setNombre("ejgv_num_registro");
		metadatos.add(metadato);

		metadato = new Metadato();
		metadato.setNombre("ejgv_fecha_registro");
		metadatos.add(metadato);

		metadato = new Metadato();
		metadato.setNombre("ejgv_fecha_registro");
		metadatos.add(metadato);

		metadato = new Metadato();
		metadato.setNombre("ejgv_formato_registro");
		metadatos.add(metadato);

		metadato = new Metadato();
		metadato.setNombre("ejgv_libro_registro");
		metadatos.add(metadato);

		metadato = new Metadato();
		metadato.setNombre("ejgv_registrado");
		metadatos.add(metadato);

		metadato = new Metadato();
		metadato.setNombre("ejgv_procedimiento");
		metadatos.add(metadato);

		metadato = new Metadato();
		metadato.setNombre("ejgv_expediente");
		metadatos.add(metadato);

		metadato = new Metadato();
		metadato.setNombre("ejgv_entidad");
		metadatos.add(metadato);

		metadato = new Metadato();
		metadato.setNombre("ejgv_departamento");
		metadatos.add(metadato);

		metadato = new Metadato();
		metadato.setNombre("ejgv_proc_infraestructura");
		metadatos.add(metadato);

		metadato = new Metadato();
		metadato.setNombre("ejgv_tipo_titularoaport");
		metadatos.add(metadato);

		metadato = new Metadato();
		metadato.setNombre("ejgv_num_titularoaport");
		metadatos.add(metadato);

		metadato = new Metadato();
		metadato.setNombre("ejgv_ap1_titularoaport");
		metadatos.add(metadato);

		metadato = new Metadato();
		metadato.setNombre("ejgv_ap2_titularoaport");
		metadatos.add(metadato);

		metadato = new Metadato();
		metadato.setNombre("ejgv_archivado");
		metadatos.add(metadato);

		metadato = new Metadato();
		metadato.setNombre("ejgv_subsistema_archivo");
		metadatos.add(metadato);

		metadato = new Metadato();
		metadato.setNombre("ejgv_fecha_archivo");
		metadatos.add(metadato);

		metadato = new Metadato();
		metadato.setNombre("ejgv_cod_familia");
		metadatos.add(metadato);

		metadato = new Metadato();
		metadato.setNombre("ejgv_idioma");
		metadatos.add(metadato);

		metadato = new Metadato();
		metadato.setNombre("ejgv_fecha_documento");
		metadatos.add(metadato);

		metadato = new Metadato();
		metadato.setNombre("ejgv_naturaleza");
		metadatos.add(metadato);

		metadato = new Metadato();
		metadato.setNombre("ejgv_fecha_digitalizacion");
		metadatos.add(metadato);

		metadato = new Metadato();
		metadato.setNombre("ejgv_estado");
		metadatos.add(metadato);

		metadato = new Metadato();
		metadato.setNombre("ejgv_fecha_vigencia");
		metadatos.add(metadato);

		metadato = new Metadato();
		metadato.setNombre("ejgv_anyo_ejercicio");
		metadatos.add(metadato);

		metadato = new Metadato();
		metadato.setNombre("ejgv_es_firmacontenida");
		metadatos.add(metadato);

		metadato = new Metadato();
		metadato.setNombre("ejgv_id_firmantes");
		metadatos.add(metadato);

		metadato = new Metadato();
		metadato.setNombre("ejgv_nom_firmantes");
		metadatos.add(metadato);

		metadato = new Metadato();
		metadato.setNombre("ejgv_es_infraestructura");
		metadatos.add(metadato);

		metadato = new Metadato();
		metadato.setNombre("ejgv_es_editable");
		metadatos.add(metadato);

		metadato = new Metadato();
		metadato.setNombre("ejgv_es_apoyo");
		metadatos.add(metadato);

		return metadatos;
	}

	@Override
	public List<FirmaInfo> retrieveSignaturesInfo(String oid) throws Exception {
		T65StringListType keysList = T65StringListType.Factory.newInstance();
		List<FirmaInfo> firmaInfoList = new ArrayList<FirmaInfo>();
		keysList.addElement(Constantes.INTERN_ID_FIRMANTES);
		keysList.addElement(Constantes.INTERN_NOM_FIRMANTES);
		String strToken = UtilTokenXlnets.getTokenStringXLNets(Constantes.COD_APLICACION);
		String auditUser = UtilSeguridad.getAuditUser();
		SignatureList signatures = retrieveSignatures(strToken, oid);
		String[] idFirmantes = null;
		String[] nomFirmantes = null;
		T65DocumentType signaturesMetadata = this.retrieveDocument(strToken, auditUser, oid, null, keysList);

		if (signaturesMetadata != null && signaturesMetadata.getAttributeList() != null
				&& signaturesMetadata.getAttributeList().getAttributeArray() != null
				&& signaturesMetadata.getAttributeList().getAttributeArray().length > 0) {
			for (T65AttributeType attibuteType : signaturesMetadata.getAttributeList().getAttributeArray()) {
				if (Constantes.INTERN_ID_FIRMANTES.equalsIgnoreCase(attibuteType.getKey())) {
					idFirmantes = attibuteType.getValue().split("#");
				} else if (Constantes.INTERN_NOM_FIRMANTES.equalsIgnoreCase(attibuteType.getKey())) {
					nomFirmantes = attibuteType.getValue().split("#");
				}
			}
			if (signatures != null) {
				setSignaturesToFirmaInfo(firmaInfoList, signatures, idFirmantes, nomFirmantes);
			} else {
				int index = 0;
				for (String idFirmante : idFirmantes) {
					FirmaInfo firmaInfo = new FirmaInfo();
					firmaInfo.setIdFirmante(idFirmante);
					firmaInfo.setNomFirmante(nomFirmantes[index]);
					firmaInfo.setFechaFirma("");
					firmaInfo.setEstado("PENDIENTE");
					firmaInfoList.add(firmaInfo);
					index++;
				}
			}
		}

		return firmaInfoList;

	}

	public SignatureList retrieveSignatures(String strToken, String strOid) {
		DokusiServiceImpl.logger.info("En ClienteDokusiService.fncRetrieveDocument");
		try {
			// DokusiConfig dokusiConfig = this.obtenerDokusiConfig();
			// Valores por defecto, si no se indican
			if (Utilidades.esBlancoNulo(strToken)) {
				strToken = UtilTokenXlnets.getTokenStringXLNets(Constantes.COD_APLICACION);
			}
			// strAuditUser = WebServiceUtiles.obtenerAuditUserDefecto(strAuditUser,
			// dokusiConfig.getCodAplicToken());
			String strAuditUser = UtilSeguridad.getAuditUser();
			// Parsea objetos a cadenas

			String paramStrOid = DokusiXMLBeanParserConverter.parseToStringDocumentID(strOid);

			// Llama servicio (segun documento UDA, con url de properties)
			String strXmlResp = this.t65BFSDWSClasePort.retrieveSignatures(strToken, strAuditUser, paramStrOid, "");
			return PlateaUtils.unmarshalSignatureList(strXmlResp);

//			T65DocumentType objResp = DokusiXMLBeanParserConverter.parseToT65BDocument(strXmlResp);

		} catch (Exception e) {
			DokusiServiceImpl.logger.error("Excepcion ClienteDokusiService.fncRetrieveDocument", e);
			return null;
		}
	}

	private T65DocumentType retrieveDocument(String strToken, String strAuditUser, String strOid,
			T65ContentType content, T65StringListType keysList) {
		DokusiServiceImpl.logger.info("En ClienteDokusiService.fncRetrieveDocument");
		try {
			// DokusiConfig dokusiConfig = this.obtenerDokusiConfig();
			// Valores por defecto, si no se indican
			if (Utilidades.esBlancoNulo(strToken)) {
				strToken = UtilTokenXlnets.getTokenStringXLNets(Constantes.COD_APLICACION);
			}
			// strAuditUser = WebServiceUtiles.obtenerAuditUserDefecto(strAuditUser,
			// dokusiConfig.getCodAplicToken());
			strAuditUser = UtilSeguridad.getAuditUser();
			// Parsea objetos a cadenas
			String paramStrContent = DokusiXMLBeanParserConverter.parseToStringContent(content);
			String paramStrOid = DokusiXMLBeanParserConverter.parseToStringDocumentID(strOid);
			String paramStrKeysList = DokusiXMLBeanParserConverter.parseToStringStringList(keysList);

			// Llama servicio (segun documento UDA, con url de properties)
			String strXmlResp = this.t65BFSDWSClasePort.retrieveDocument(strToken, strAuditUser, paramStrOid,
					paramStrKeysList, paramStrContent);
			T65DocumentType objResp = DokusiXMLBeanParserConverter.parseToT65BDocument(strXmlResp);

			DokusiServiceImpl.logger.info("Fin fncRetrieveDocument");
			return objResp;
		} catch (Exception e) {
			DokusiServiceImpl.logger.error("Excepcion ClienteDokusiService.fncRetrieveDocument", e);
			return null;
		}
	}

	public void setSignaturesToFirmaInfo(List<FirmaInfo> firmaInfoList, SignatureList signatures, String[] idFirmantes,
			String[] nomFirmantes) {
		for (SignatureType signatureInfo : signatures.getSignature()) {
			for (SignatureInfoType signatureInfoType : signatureInfo.getSignatureInfoList().getSignatureInfo()) {
				int index = 0;
				for (String idFirmante : idFirmantes) {
					FirmaInfo firmaInfo = new FirmaInfo();
					if (idFirmante.equalsIgnoreCase(signatureInfoType.getSignerID())) {
						firmaInfo.setIdFirmante(signatureInfoType.getSignerID());
						firmaInfo.setNomFirmante(signatureInfoType.getSignerName());
						if (signatureInfo.getDate() != null) {
							firmaInfo.setFechaFirma(signatureInfo.getDate());
							firmaInfo.setEstado("FIRMADO");
						} else {
							firmaInfo.setEstado("PENDIENTE");
						}
						firmaInfoList.add(firmaInfo);
					} else {
						firmaInfo.setIdFirmante(idFirmante);
						firmaInfo.setNomFirmante(nomFirmantes[index]);
						firmaInfo.setFechaFirma("");
						firmaInfo.setEstado("PENDIENTE");
						firmaInfoList.add(firmaInfo);
					}
					index++;
				}

			}

		}
	}

	@Override
	public Root searchDocumentsDossier(String documentalType, String dniUser, String inforce, int intMaxRows) {
		Root result = new Root();
		try {
			documentalType = PlateaUtils.extractDocumentalType(documentalType);
			String strToken = UtilTokenXlnets.getTokenStringXLNets(Constantes.COD_APLICACION);
			String auditUser = UtilSeguridad.getAuditUser();
			T65StringListType attributeList = T65StringListType.Factory.newInstance();
			T65ConditionListType conditionListType = T65ConditionListType.Factory.newInstance();
			attributeList.addElement(GENERIC_OBJECT_NAME);
			attributeList.addElement(INTERN_NATURALEZA);
			attributeList.addElement(GENERIC_CREATION_DATE);
			T65ConditionType condition = conditionListType.addNewCondition();
			T65AttributeType attribute = T65AttributeType.Factory.newInstance();
			attribute.setKey(NUM_TITULARAPORT);
			attribute.setValue(dniUser);
			condition.setAttribute(attribute);
			condition.setOperator("=");
			String returnedAttributeKeysList = DokusiXMLBeanParserConverter.parseToStringStringList(attributeList);
			returnedAttributeKeysList = returnedAttributeKeysList
					.replaceAll("xmlns:fsd=\"com/ejie/t65/jaxb/beans/fsd\"", "").replaceAll("fsd:", "");
			String searchConditionsList = DokusiXMLBeanParserConverter.parseToStringCondition(conditionListType);
			searchConditionsList = searchConditionsList.replaceAll("xmlns:fsd=\"com/ejie/t65/jaxb/beans/fsd\"", "")
					.replaceAll("fsd:", "");
			String xmlResult = this.x98DossierWebService.searchDocumentsDossier(strToken, auditUser,
					returnedAttributeKeysList, searchConditionsList, documentalType, inforce, dniUser, intMaxRows);
			result = DokusiXMLBeanParserConverter.unmarshallDossierDokusiPResponse(xmlResult);

		} catch (Exception e) {
			DokusiServiceImpl.logger.error("Excepcion ClienteDokusiService.searchDocumentsDossier", e);

		}
		return result;
	}

}