package com.ejie.ad74a.util.pif;

import java.io.InputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Document;

import com.ejie.ad74a.constantes.Constantes;
import com.ejie.ad74a.exceptions.Ad74aWebserviceException;
import com.ejie.ad74a.util.comun.UtilTokenXlnets;
import com.ejie.y31.exception.Y31JanoServiceAccesDeniedException;
import com.ejie.y31.exception.Y31JanoServiceEventJmsException;
import com.ejie.y31.exception.Y31JanoServiceFileNameFormatException;
import com.ejie.y31.exception.Y31JanoServiceFileNotFoundException;
import com.ejie.y31.exception.Y31JanoServiceGenericException;
import com.ejie.y31.exception.Y31JanoServiceMongoDbGenericException;
import com.ejie.y31.exception.Y31JanoServiceOracleGenericException;
import com.ejie.y31.factory.Y31JanoServiceAbstractFactory;
import com.ejie.y31.service.Y31JanoService;
import com.ejie.y31.vo.Y31AttachmentBean;

/**
 * Utilidad para invocar al WS de Platea Integración Ficheros
 * 
 * @author olillo
 * 
 */
public class Ad74aPIFws {

	private static Ad74aPIFws instance;
	private Y31JanoService webservice;

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

	/**
	 * Constructor
	 * 
	 * @throws Ad74aWebserviceException Excepcion al invocar el WS
	 */
	public Ad74aPIFws() throws Ad74aWebserviceException {
		try {
			this.webservice = Y31JanoServiceAbstractFactory.getInstance();
		} catch (Y31JanoServiceGenericException e) {
			throw new Ad74aWebserviceException("Error al instanciar el WS de PIF: " + e.getCause());
		}
	}

	/**
	 * Descarga el documento desde la ruta especificada y lo devuelve como Stream d
	 * entrada
	 * 
	 * @param path la ruta
	 * @return el stream
	 * @throws Ad74aWebserviceException excepción de invocación al servicio
	 */
	public InputStream downloadDocument(String path) throws Ad74aWebserviceException {
		try {
			// GET --> PARAMETROS
			// - Xlnets - Document --> Sesión de aplicación que está escribiendo
			// en el repositorio
			// - pathFrom - String --> Ruta lógica de donde se va a descargar el
			// fichero. Incluirá como carpeta principal la aplicación destino
			//
			// * return: File - InputStream --> Stream de datos para acceder al
			// contenido existente en el repositorio
			// ************** contentType - String --> content type del fichero
			// ************** fileName - String --> nombre del fichero
			// ************** filePath - String --> ruta completa al fichero
			// ************** size - Long --> número de bytes del fichero

			return this.webservice.get(UtilTokenXlnets.getTokenDocumentXLNets(Constantes.COD_APLICACION), path);
		} catch (Y31JanoServiceGenericException e) {
			throw new Ad74aWebserviceException("Error descargar el fichero (Excepción genérica): " + e.getCause());
		} catch (Y31JanoServiceFileNotFoundException e) {
			throw new Ad74aWebserviceException("Error descargar el fichero (Archivo no encontrado): " + e.getCause());
		} catch (Y31JanoServiceFileNameFormatException e) {
			throw new Ad74aWebserviceException(
					"Error descargar el fichero (Formato de fichero no soportado): " + e.getCause());
		} catch (Y31JanoServiceMongoDbGenericException e) {
			throw new Ad74aWebserviceException(
					"Error descargar el fichero (Error de BB.DD.[MongoDB]): " + e.getCause());
		} catch (Y31JanoServiceOracleGenericException e) {
			throw new Ad74aWebserviceException("Error descargar el fichero (Error de BB.DD.[Oracle]): " + e.getCause());
		} catch (Y31JanoServiceAccesDeniedException e) {
			throw new Ad74aWebserviceException("Error descargar el fichero (Accedo denegado): " + e.getCause());
		}
	}

	/**
	 * Sube a la ruta de la zona pif que se pasa como parámetro el documento
	 * accedido por el inpuStream
	 * 
	 * @param stream       Stream del documento
	 * @param path         ruta en la que se va a dejar el documento (incluyendo el
	 *                     nombre de archivo y extensión)
	 * @param preserveName Indica si se desea preservar el nombre del fichero en la
	 *                     ruta seleccionada sobrescribiendo el fichero si
	 *                     existiera. Si se decide no preservar los nombres lo que
	 *                     se hace es concatenarle una serie de dígitos que lo hace
	 *                     único en el repositorio
	 * @return la ruta en la que se deja el documento
	 * @throws Ad74aWebserviceException Excepción de invocación al servicio
	 */
	public String uploadDocument(InputStream stream, String path, boolean preserveName)
			throws Ad74aWebserviceException {
		try {
			// PUT --> PARAMETROS
			// - Xlnets - Document --> Sesión de aplicación que está escribiendo
			// en el repositorio
			// - File - InputStream --> Stream de datos para acceder al
			// contenido a copiar en el repositorio
			// - pathTo - String --> Ruta lógica donde alojar el fichero.
			// Incluirá como carpeta principal la aplicación destino
			// - preserveName - boolean --> Indica si se desea preservar el
			// nombre del fichero en la ruta seleccionada sobrescribiendo el
			// fichero si existiera. Si se decide no preservar los nombres lo
			// que se hace es concatenarle una serie de dígitos que lo hace
			// único en el repositorio
			// - Ttl - Long --> Número de segundos que se desea mantener el
			// fichero en el repositorio. Como máximo se podrá fijar el número
			// de segundos de 15 días naturales
			//
			// * return: File - InputStream --> Stream de datos para acceder al
			// contenido existente en el repositorio
			// ************** contentType - String --> content type del fichero
			// ************** fileName - String --> nombre del fichero
			// ************** filePath - String --> ruta completa al fichero
			// ************** size - Long --> número de bytes del fichero

			Document documentToken = UtilTokenXlnets.getTokenDocumentXLNets(Constantes.COD_APLICACION);
			Y31AttachmentBean resul = this.webservice.put(documentToken, stream, path, preserveName,
					Constantes.PIF_TTL);
			return resul.getFilePath();
		} catch (Y31JanoServiceGenericException e) {
			throw new Ad74aWebserviceException("Error al subir el fichero (Excepción genérica): " + e.getCause());
		} catch (Y31JanoServiceFileNameFormatException e) {
			throw new Ad74aWebserviceException(
					"Error al subir el fichero (Formato de fichero no soportado) : " + e.getCause());
		} catch (Y31JanoServiceMongoDbGenericException e) {
			throw new Ad74aWebserviceException("Error al subir el fichero (Error de BB.DD.): " + e.getCause());
		} catch (Y31JanoServiceEventJmsException e) {
			throw new Ad74aWebserviceException("Error al subir el fichero (Error JMS): " + e.getCause());
		} catch (Y31JanoServiceAccesDeniedException e) {
			throw new Ad74aWebserviceException("Error al subir el fichero (Acceso denegado): " + e.getCause());
		} catch (Exception e) {
			throw new Ad74aWebserviceException("Error: " + e.getCause());
		}
	}

	/**
	 * Mueve el documento en la ruta origen a la ruta destino
	 * 
	 * @param pathOrigen  ruta en la que está el documento
	 * @param pathDestino ruta en la que se va a dejar el documento
	 * @return la ruta en la que se deja el documento
	 * @throws Ad74aWebserviceException Excepción de invocación al servicio
	 */
	public String moveDocument(String pathOrigen, String pathDestino) throws Ad74aWebserviceException {
		try {
			// MOVE --> PARAMETROS
			// - Xlnets - Document --> Sesión de aplicación que está escribiendo
			// en el repositorio
			// - pathFrom - String --> Ruta lógica desde donde se va a mover el
			// fichero. Incluirá como carpeta principal la aplicación origen
			// - pathTo - String --> Ruta lógica donde se va a mover el fichero.
			// Incluirá como carpeta principal la aplicación destino
			// - preserveName - boolean --> Indica si se desea preservar el
			// nombre del fichero en la ruta seleccionada sobrescribiendo el
			// fichero si existiera. Si se decide no preservar los nombres lo
			// que se hace es concatenarle una serie de dígitos que lo hace
			// único en el repositorio
			//
			// * return: File - InputStream --> Stream de datos para acceder al
			// contenido existente en el repositorio
			// ************** contentType - String --> content type del fichero
			// ************** fileName - String --> nombre del fichero
			// ************** filePath - String --> ruta completa al fichero
			// ************** size - Long --> número de bytes del fichero

			Y31AttachmentBean resul = this.webservice.move(
					UtilTokenXlnets.getTokenDocumentXLNets(Constantes.COD_APLICACION), pathOrigen, pathDestino, true);
			return resul.getFilePath();
		} catch (Y31JanoServiceGenericException e) {
			throw new Ad74aWebserviceException("Error al mover el fichero (Excepción genérica): " + e.getCause());
		} catch (Y31JanoServiceFileNameFormatException e) {
			throw new Ad74aWebserviceException(
					"Error al mover el fichero (Formato de fichero no soportado) : " + e.getCause());
		} catch (Y31JanoServiceMongoDbGenericException e) {
			throw new Ad74aWebserviceException("Error al mover el fichero (Error de BB.DD.): " + e.getCause());
		} catch (Y31JanoServiceEventJmsException e) {
			throw new Ad74aWebserviceException("Error al mover el fichero (Error JMS): " + e.getCause());
		} catch (Y31JanoServiceAccesDeniedException e) {
			throw new Ad74aWebserviceException("Error al mover el fichero (Acceso denegado): " + e.getCause());
		} catch (Y31JanoServiceFileNotFoundException e) {
			throw new Ad74aWebserviceException("Error al mover el fichero (Archivo no encontrado): " + e.getCause());
		}
	}

	/**
	 * Copia el documento en la ruta origen a la ruta destino
	 * 
	 * @param pathOrigen   ruta en la que está el documento
	 * @param pathDestino  ruta en la que se va a dejar el documento
	 * @param preserveName indica si sobreescribe (true) o crea un nuevo documento
	 *                     (false)
	 * @return la ruta en la que se deja el documento
	 * @throws Ad74aWebserviceException Excepción de invocación al servicio
	 */
	public String copyDocument(String pathOrigen, String pathDestino, boolean preserveName)
			throws Ad74aWebserviceException {
		try {
			// COPY --> PARAMETROS
			// - Xlnets - Document --> Sesión de aplicación que está escribiendo
			// en el repositorio
			// - pathFrom - String --> Ruta lógica desde donde se va a mover el
			// fichero. Incluirá como carpeta principal la aplicación origen
			// - pathTo - String --> Ruta lógica donde se va a mover el fichero.
			// Incluirá como carpeta principal la aplicación destino
			// - preserveName - boolean --> Indica si se desea preservar el
			// nombre del fichero en la ruta seleccionada sobrescribiendo el
			// fichero si existiera. Si se decide no preservar los nombres lo
			// que se hace es concatenarle una serie de dígitos que lo hace
			// único en el repositorio
			//
			// * return: File - InputStream --> Stream de datos para acceder al
			// contenido existente en el repositorio
			// ************** contentType - String --> content type del fichero
			// ************** fileName - String --> nombre del fichero
			// ************** filePath - String --> ruta completa al fichero
			// ************** size - Long --> número de bytes del fichero
			Y31AttachmentBean resul = this.webservice.copy(
					UtilTokenXlnets.getTokenDocumentXLNets(Constantes.COD_APLICACION), pathOrigen, pathDestino,
					preserveName);
			// TODO mirar resultado del servicio web. Si "success" es false
			// notificarlo (lanzar excepcion)
			return resul.getFilePath();
		} catch (Y31JanoServiceGenericException e) {
			throw new Ad74aWebserviceException("Error al copiar el fichero (Excepción genérica): " + e.getCause());
		} catch (Y31JanoServiceFileNameFormatException e) {
			throw new Ad74aWebserviceException(
					"Error al copiar el fichero (Formato de fichero no soportado) : " + e.getCause());
		} catch (Y31JanoServiceMongoDbGenericException e) {
			throw new Ad74aWebserviceException("Error al copiar el fichero (Error de BB.DD.): " + e.getCause());
		} catch (Y31JanoServiceAccesDeniedException e) {
			throw new Ad74aWebserviceException("Error al copiar el fichero (Acceso denegado): " + e.getCause());
		} catch (Y31JanoServiceEventJmsException e) {
			throw new Ad74aWebserviceException("Error al copiar el fichero (Error JMS): " + e.getCause());
		} catch (Y31JanoServiceFileNotFoundException e) {
			throw new Ad74aWebserviceException("Error al copiar el fichero (Archivo no encontrado): " + e.getCause());
		}
	}

	/**
	 * Consulta el documento en la ruta
	 * 
	 * @param path ruta en la que está el documento
	 * @return la ruta en la que se deja el documento
	 * @throws Ad74aWebserviceException Excepción de invocación al servicio
	 */
	public Map<String, String> infoDocument(String path) throws Ad74aWebserviceException {

		HashMap<String, String> resultado = new HashMap<>();
		try {
			// INFO --> PARAMETROS
			// - Xlnets - Document --> Sesión de aplicación que está escribiendo
			// en el repositorio
			// - pathFrom - String --> Ruta lógica desde donde se va a consultar
			// el
			// fichero. Incluirá como carpeta principal la aplicación origen
			//
			// * return: File - InputStream --> Stream de datos para acceder al
			// contenido existente en el repositorio
			// ************** contentType - String --> content type del fichero
			// ************** fileName - String --> nombre del fichero
			// ************** filePath - String --> ruta completa al fichero
			// ************** size - Long --> número de bytes del fichero
			Y31AttachmentBean resul = this.webservice
					.info(UtilTokenXlnets.getTokenDocumentXLNets(Constantes.COD_APLICACION), path);
			resultado.put("contentType", resul.getContentType());
			resultado.put("fileName", resul.getFileName());
			resultado.put("filePath", resul.getFilePath());
			resultado.put("size", resul.getSize().toString());

			return resultado;
		} catch (Y31JanoServiceFileNameFormatException e) {
			throw new Ad74aWebserviceException(
					"Error al recuperar info del fichero (Formato de fichero no soportado) : " + e.getCause());
		} catch (Y31JanoServiceMongoDbGenericException e) {
			throw new Ad74aWebserviceException(
					"Error al recuperar info del fichero (Error de BB.DD.): " + e.getCause());
		} catch (Y31JanoServiceAccesDeniedException e) {
			throw new Ad74aWebserviceException(
					"Error al recuperar info del fichero (Acceso denegado): " + e.getCause());
		} catch (Y31JanoServiceFileNotFoundException e) {
			throw new Ad74aWebserviceException(
					"Error al recuperar info del fichero (Archivo no encontrado): " + e.getCause());
		} catch (Y31JanoServiceGenericException e) {
			throw new Ad74aWebserviceException(
					"Error al recuperar info del fichero (Excepción genérica): " + e.getCause());
		}
	}

	/**
	 * Elimina el documento en la ruta
	 * 
	 * @param path ruta en la que está el documento
	 * @throws Ad74aWebserviceException Excepción de invocación al servicio
	 */
	public void deleteDocument(String path) throws Ad74aWebserviceException {
		try {
			// DELETE --> PARAMETROS
			// - Xlnets - Document --> Sesión de aplicación que está escribiendo
			// en el repositorio
			// - pathFrom - String --> Ruta lógica desde donde se va a eliminar
			// el
			// fichero. Incluirá como carpeta principal la aplicación origen
			//
			// * return: File - InputStream --> Stream de datos para acceder al
			// contenido existente en el repositorio
			// ************** contentType - String --> content type del fichero
			// ************** fileName - String --> nombre del fichero
			// ************** filePath - String --> ruta completa al fichero
			// ************** size - Long --> número de bytes del fichero
			this.webservice.delete(UtilTokenXlnets.getTokenDocumentXLNets(Constantes.COD_APLICACION), path);
		} catch (Y31JanoServiceGenericException e) {
			throw new Ad74aWebserviceException("Error al eliminar el fichero (Excepción genérica): " + e.getCause());
		} catch (Y31JanoServiceFileNameFormatException e) {
			throw new Ad74aWebserviceException(
					"Error al eliminar el fichero (Formato de fichero no soportado) : " + e.getCause());
		} catch (Y31JanoServiceAccesDeniedException e) {
			throw new Ad74aWebserviceException("Error al eliminar el fichero (Acceso denegado): " + e.getCause());
		} catch (Y31JanoServiceFileNotFoundException e) {
			throw new Ad74aWebserviceException("Error al eliminar el fichero (Archivo no encontrado): " + e.getCause());
		}
	}

	public static String copiarZonaPlatea(Document token, String rutaPIF) {
		Ad74aPIFws.LOGGER.info("- Copiando archivo {} a zona Platea...", rutaPIF);
		StringBuilder rutaDestino = new StringBuilder();
		rutaDestino.append("/r02g/").append(Constantes.COD_APLICACION.toLowerCase()).append("/")
				.append(obtenerNombreFichero(rutaPIF));

		Ad74aPIFws.LOGGER.info("- Copiando archivo {} a zona Platea: {}", rutaPIF, rutaDestino);

		try {
			Y31JanoService service = Y31JanoServiceAbstractFactory.getInstance();
			Y31AttachmentBean resultado = service.copy(token, rutaPIF, rutaDestino.toString(), true);

			return resultado.getFilePath();
		} catch (Exception e) {
			Ad74aPIFws.LOGGER.error("Error en UtilesPIF.copiarZonaPlatea", e);
			return null;
		}
	}

	/**
	 * A partir de una ruta completa de PIF, obtiene el nombre (y extensiÃ³n) del
	 * fichero
	 * 
	 * @param rutaCompletaPIF Ruta completa en PIF
	 * @return Cadena con el nombre (y extension) del fichero.
	 */
	public static String obtenerNombreFichero(String rutaCompletaPIF) {
		return UtilesPath.obtenerNombreDelPath(rutaCompletaPIF, "/", true);
	}

	/**
	 * Lista los documentos existentes en la ruta
	 * 
	 * @param path ruta en la que se encuentran los documentos a listar
	 * @return la lista de documentos
	 * @throws Excepci贸n d einvocaci贸n al servicio
	 */
	public List<Y31AttachmentBean> listFile(String path) throws Ad74aWebserviceException {
		try {
			@SuppressWarnings("unchecked")
			List<Y31AttachmentBean> resul = this.webservice
					.list(UtilTokenXlnets.getTokenDocumentXLNets(Constantes.COD_APLICACION), path);
			return resul;
		} catch (Exception e) {
			throw new Ad74aWebserviceException("Error al listar ficheros: " + e.getCause());
		} catch (Throwable t) {// NOSONAR englobar cualquier error en Ad74aWebserviceException
			throw new Ad74aWebserviceException("Error al subir el fichero - Error no controlado: " + t.getCause());
		}
	}

	/**
	 * Devuelve la instancia de tipo Ad74aPIFws
	 * 
	 * @return Devuelve la instancia de tipo Ad74aPIFws
	 */
	public static final Ad74aPIFws getInstance() {
		if (Ad74aPIFws.instance == null) {
			try {
				Ad74aPIFws.instance = new Ad74aPIFws();
			} catch (Ad74aWebserviceException e) {
				Ad74aPIFws.LOGGER.error("Error en Ad74aPIFws.getInstance(): ", e);
			}
		}
		return Ad74aPIFws.instance;
	}

	public String buildPath(String... paths) {
		if (paths == null) {
			return "";
		} else {
			StringBuilder sb = new StringBuilder();
			String[] var5 = paths;
			int var4 = paths.length;

			String newPath;
			for (int var3 = 0; var3 < var4; ++var3) {
				newPath = var5[var3];
				if (newPath == null) {
					return "";
				}

				sb.append(newPath);
			}
			return sb.toString().replace("//", "/");
		}
	}
}
