package com.ejie.ab04b.util.ws.documentgenerator;

import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;

import com.ejie.ab04b.exception.AB04BException;
import com.ejie.ab04b.service.pif.PifService;
import com.ejie.ab04b.service.util.ApplicationContextProvider;
import com.ejie.ab04b.util.PropertiesUtil;
import com.ejie.ab04b.webservice.client.documentowebservice.DocumentoWebServiceImpl;

/**
 * Utilidad para invocar a los servicios de generación de fichero s de aa19b
 * 
 * @author dcarranz
 * 
 */
public class Ab04bDocumentGeneratorWS {

	private static Ab04bDocumentGeneratorWS instance;

	private static final Logger LOGGER = LoggerFactory
			.getLogger(Ab04bDocumentGeneratorWS.class);

	@Autowired()
	private DocumentoWebServiceImpl webservice;

	private PifService pifWS;

	/**
	 * Constructor.
	 *
	 * @throws AB04BException             Excepcion
	 */
	public Ab04bDocumentGeneratorWS() throws AB04BException {
		ApplicationContext ctx = ApplicationContextProvider
				.getApplicationContext();

		this.pifWS = PifService.getInstance();
		this.webservice = (DocumentoWebServiceImpl) ctx
				.getBean("documentoWebService");
	}

	/**
	 * Genera el documento y lo devuenve como stream de entrada, para que se
	 * pueda tratar correctamente (Si devolviésemos por ejemplo, un array de
	 * bytes, podría desbordarse la memoria, en el caso de documentos
	 * excepcionalmente grandes)
	 * 
	 *  datosXML
	 *            XML con los datos necesarios para generar el documento. Se
	 *            asume que su tamaño será moderado.
	 *  streamPlantilla
	 *            Stream con la plantilla (sin restricicones de tamaño)
	 *  El stream del documento genradao
	 *
	 * @param datosXML the datos XML
	 * @param streamPlantilla the stream plantilla
	 * @return the input stream
	 * @throws AB04BException             Excepción al invocar el servicio
	 */
	public InputStream generateDocument(InputStream datosXML,
			InputStream streamPlantilla) throws AB04BException {

		try {

			// rutas temporales para los documentos en PIF
			StringBuilder pathXml = new StringBuilder();
			StringBuilder pathPlantilla = new StringBuilder();
			StringBuilder pathDocumentoGenerado = new StringBuilder();
			pathXml.append(
					PropertiesUtil.getProperty(PropertiesUtil.PIF_RUTA_APP))
					.append("xml_temporal").append(".xml");

			pathPlantilla
					.append(PropertiesUtil
							.getProperty(PropertiesUtil.PIF_RUTA_APP))
					.append("rtf_temporal").append(".rtf");

			pathDocumentoGenerado
					.append(PropertiesUtil
							.getProperty(PropertiesUtil.PIF_RUTA_APP))
					.append(generateUID()).append(".doc");

			// Subir el xml y la plantilla a PIF
			String pathPifDatos = this.pifWS.uploadDocument(datosXML,
					pathXml.toString(), false);

			String pathPifPlantilla = this.pifWS.uploadDocument(
					streamPlantilla, pathPlantilla.toString(), false);

			// Generar el documento
			String pathPifDocumentoGenerado = this.webservice.create(
					pathPifDatos, pathPifPlantilla,
					pathDocumentoGenerado.toString());
			// Descargar el documento de PIF y devolver el resultado
			return this.pifWS.downloadDocument(pathPifDocumentoGenerado);
		} catch (Exception e) {
			throw new AB04BException("Encoding UTF-8 no soportado: " + e);
		}

	}

	/**
	 * Genera el documento y devuelve su ruta pif, para que se pueda tratar
	 * correctamente (Si devolviésemos por ejemplo, un array de bytes, podría
	 * desbordarse la memoria, en el caso de documentos excepcionalmente
	 * grandes)
	 * 
	 *  datosXML
	 *            XML con los datos necesarios para generar el documento. Se
	 *            asume que su tamaño será moderado.
	 *  plantilla
	 *            Stream con la plantilla (sin restricicones de tamaño)
	 *  La ruta pif del documento generado
	 *
	 * @param datosXML the datos XML
	 * @param plantilla the plantilla
	 * @return the string
	 * @throws AB04BException             Excepción al invocar el servicio
	 */
	public String generateDocumentRuta(byte[] datosXML, byte[] plantilla)
			throws AB04BException {

		try {
			// rutas temporales para los documentos en PIF
			StringBuilder pathXml = new StringBuilder();
			StringBuilder pathPlantilla = new StringBuilder();
			StringBuilder pathDocumentoGenerado = new StringBuilder();
			pathXml.append(
					PropertiesUtil.getProperty(PropertiesUtil.PIF_RUTA_APP))
					.append(generateUID()).append(".xml");

			pathPlantilla
					.append(PropertiesUtil
							.getProperty(PropertiesUtil.PIF_RUTA_APP))
					.append(generateUID()).append(".rtf");

			pathDocumentoGenerado
					.append(PropertiesUtil
							.getProperty(PropertiesUtil.PIF_RUTA_APP))
					.append(generateUID()).append(".doc");

			// Subir el xml
			String pathPifDatos = this.pifWS.uploadDocument(
					new ByteArrayInputStream(datosXML), pathXml.toString(),
					false);

			// Subir la plantilla
			String pathPifPlantilla = this.pifWS.uploadDocument(
					new ByteArrayInputStream(plantilla),
					pathPlantilla.toString(), false);

			// Generar el documento
			return this.webservice.create(pathPifDatos, pathPifPlantilla,
					pathDocumentoGenerado.toString());
		} catch (Exception e) {
			Ab04bDocumentGeneratorWS.LOGGER.error(
					"error método generateDocumentRuta: ", e);
			throw new AB04BException("error método generateDocumentRuta: "
					+ e.getMessage());
		}

	}

	/**
	 * Recibe un listado de XMLS y genera un .ZIP con los documentos generados
	 * 
	 *  listadoXMLs
	 *            List<InputStream>
	 *  streamPlantilla
	 *            InputStream
	 *  InputStream
	 *
	 * @param listadoXMLs the listado XM ls
	 * @param streamPlantilla the stream plantilla
	 * @return the input stream
	 * @throws AB04BException             AB04BException
	 */
	public InputStream generateDocumentMulti(List<InputStream> listadoXMLs,
			InputStream streamPlantilla) throws AB04BException {

		try {
			// Subir la plantilla RTF a PIF
			StringBuilder pathPlantilla = new StringBuilder();
			pathPlantilla
					.append(PropertiesUtil
							.getProperty(PropertiesUtil.PIF_RUTA_APP))
					.append(generateUID()).append(".rtf");
			String pathPifPlantilla = this.pifWS.uploadDocument(
					streamPlantilla, pathPlantilla.toString(), false);

			// Subir todos los documentos XML a PIF
			// Generar a la vez un listado con la ruta PIF de los XML
			List<String> listadoXmlString = new ArrayList<String>();

			StringBuilder pathXml = new StringBuilder();

			for (int i = 0; i < listadoXMLs.size(); i++) {
				pathXml.setLength(0);
				pathXml.append(
						PropertiesUtil.getProperty(PropertiesUtil.PIF_RUTA_APP))
						.append(generateUID()).append(".xml");
				String pathPifDatos = this.pifWS.uploadDocument(
						listadoXMLs.get(i), pathXml.toString(), false);
				listadoXmlString.add(pathPifDatos);
			}

			StringBuilder pathDocumentoGenerado = new StringBuilder();
			pathDocumentoGenerado.append(
					PropertiesUtil.getProperty(PropertiesUtil.PIF_RUTA_APP))
					.append(generateUID());

			// Generar el documento
			String pathPifDocumentoGenerado = this.webservice.createMulti(
					listadoXmlString, pathPifPlantilla,
					pathDocumentoGenerado.toString());

			// Descargar el documento de PIF y devolver el resultado
			return this.pifWS.downloadDocument(pathPifDocumentoGenerado);
		} catch (Exception e) {
			throw new AB04BException("Encoding UTF-8 no soportado: "
					+ e.getCause());
		}

	}

	/**
	 * Devuelve la instancia de tipo L61bDocumentGeneratorWS
	 * 
	 *  Devuelve la instancia de tipo L61bDocumentGeneratorWS.
	 *
	 * @return single instance of Ab04bDocumentGeneratorWS
	 * @throws AB04BException             e
	 */
	public static final Ab04bDocumentGeneratorWS getInstance()
			throws AB04BException {
		if (Ab04bDocumentGeneratorWS.instance == null) {
			try {
				Ab04bDocumentGeneratorWS.instance = new Ab04bDocumentGeneratorWS();
			} catch (AB04BException e) {
				throw new AB04BException("AB04BException" + e.getCause());
			}
		}
		return Ab04bDocumentGeneratorWS.instance;
	}

	/**
	 * Sube un fichero a la zona PIF
	 * 
	 *  stream
	 *            InputStream
	 *  ruta
	 *            String
	 *  filename
	 *            String
	 *  preserveName
	 *            boolean
	 *  String.
	 *
	 * @param stream the stream
	 * @param ruta the ruta
	 * @param filename the filename
	 * @param preserveName the preserve name
	 * @return the string
	 * @throws AB04BException             Exception
	 */
	public String uploadDocument(InputStream stream, String ruta,
			String filename, boolean preserveName) throws AB04BException {
		StringBuilder pathXml = new StringBuilder();
		pathXml.append(ruta);
		pathXml.append(filename);
		return this.pifWS.uploadDocument(stream, pathXml.toString(),
				preserveName);

	}

	/**
	 * Genera un identificador único universal
	 * 
	 *  El identificador.
	 *
	 * @return the string
	 */
	public static String generateUID() {
		return UUID.randomUUID().toString().replaceAll("\\-", "");
	}
}
