package com.ejie.ab04b.service;

import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;

import org.apache.commons.io.IOUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.ejie.ab04b.constantes.Constantes;
import com.ejie.ab04b.constantes.ConstantesNum;
import com.ejie.ab04b.dao.custom.DocumentoAperturasCustomDao;
import com.ejie.ab04b.dao.temp.DocumentosAperturasTempDao;
import com.ejie.ab04b.exception.AB04BException;
import com.ejie.ab04b.model.DocumentoAperturas;
import com.ejie.ab04b.model.TipoDocumento;
import com.ejie.ab04b.model.TramiteAperturas;
import com.ejie.ab04b.service.pif.PifService;
import com.ejie.ab04b.util.PlateaTramitacionUtils;
import com.ejie.ab04b.util.Utilities;
import com.ejie.foldermanagement.xml.DocumentEvent;
import com.ejie.x38.dto.JQGridRequestDto;
import com.ejie.x38.dto.JQGridResponseDto;
import com.ejie.x38.dto.TableRowDto;

/**
 * Ab0465s00ServiceImpl generated by UDA, 15-Feb-2017 09:14:46.
 * 
 * @author UDA
 */

@Service(value = "ab0465s00Service")
public class DocumentoAperturasServiceImpl implements DocumentoAperturasService {

	@Autowired()
	private DocumentoAperturasCustomDao ab0465s00Dao;
	@Autowired()
	private DocumentosAperturasTempDao docAperturasTempDao;
	@Autowired()
	private TipoDocumentoService tipoDocumentoService;

	@Autowired
	private PifService pifService;

	/**
	 * Inserts a single row in the Ab0465s00 table.
	 * 
	 * ab0465s00 Ab0465s00 Ab0465s00
	 * 
	 * @param ab0465s00
	 *            the ab 0465 s 00
	 * @return the documento aperturas
	 */
	@Transactional(rollbackFor = Throwable.class)
	public DocumentoAperturas add(DocumentoAperturas ab0465s00) {
		return this.ab0465s00Dao.add(ab0465s00);
	}

	/**
	 * Inserts a single row in the Ab0465s00 table.
	 * 
	 * ab0465s00 Ab0465s00 temp boolean Ab0465s00
	 * 
	 * @param ab0465s00
	 *            the ab 0465 s 00
	 * @param temp
	 *            the temp
	 * @return the documento aperturas
	 */
	@Transactional(rollbackFor = Throwable.class)
	public DocumentoAperturas add(DocumentoAperturas ab0465s00, boolean temp) {

		if (temp) {
			return this.docAperturasTempDao.add(ab0465s00);
		} else {
			return this.ab0465s00Dao.add(ab0465s00);
		}
	}

	/**
	 * Inserts a single row in the Ab0465s00 table.
	 * 
	 * documents List<DocumentEvent> fechaCreacion String idTramite Long
	 * 
	 * @param documents
	 *            the documents
	 * @param fechaCreacion
	 *            the fecha creacion
	 * @param idTramite
	 *            the id tramite
	 */
	@Transactional(rollbackFor = Throwable.class)
	public void addDocumentosSolicitud(List<DocumentEvent> documents,
			String fechaCreacion, Long idTramite) {

		for (DocumentEvent document : documents) {
			// Solo se adjuntaron los que vienen con la etiqueta <sourceName>
			if (!Utilities.getInstance().isEmpty(document.getSourceName())) {

				DocumentoAperturas docNuevo = new DocumentoAperturas();
				docNuevo.setTramiteAperturas(new TramiteAperturas(idTramite));
				docNuevo.setOrigen065(Constantes.DOCUMENTO_ORIGEN_CIUDADANO);
				docNuevo.setFechaDoc065(PlateaTramitacionUtils.getInstance()
						.parsearTimestampPlatea(fechaCreacion));
				docNuevo.setNombreDoc065(document.getSourceName());

				// TODO OID se actualiza despues????
				docNuevo.setOidDokusi065(document.getOid());

				docNuevo.setRutaPif065(document.getLocation());
				docNuevo.setFormatoAport065(Constantes.FORMATO_APORTACION_ELECTRONICO);

				// Obtenemos el tipo de documento
				String[] partesRolDocumento = document.getRoleId().split(
						"\\".concat(Constantes.SEPARADOR_PUNTO));
				TipoDocumento tipoDocumento = new TipoDocumento();
				if (partesRolDocumento != null && partesRolDocumento.length > 0) {
					tipoDocumento.setTipoDokusi091(partesRolDocumento[0]);
					tipoDocumento
							.setAsuntoDokusi091(partesRolDocumento[ConstantesNum.NUM_2]);
				}
				tipoDocumento = this.tipoDocumentoService
						.findByTipoAsuntoDocumental(tipoDocumento);
				docNuevo.setTipoDocumento(tipoDocumento);

				this.ab0465s00Dao.add(docNuevo);
			}
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * com.ejie.ab04b.service.DocumentoAperturasService#descargarDocumento(java
	 * .lang.String)
	 */
	@Override()
	public byte[] descargarDocumento(String rutaCompletaFichero)
			throws AB04BException {
		try {
			byte[] ficheroBytes = null;

			try {
				InputStream fichero = this.pifService
						.downloadDocument(rutaCompletaFichero);
				ficheroBytes = IOUtils.toByteArray(fichero);
				fichero.close();
			} catch (Exception ex) {
				throw new AB04BException(ex, ex.getMessage());
			}
			return ficheroBytes;
		} catch (Exception e) {
			throw new AB04BException(e, e.getMessage());
		}
	}

	/**
	 * Updates a single row in the Ab0465s00 table.
	 * 
	 * ab0465s00 Ab0465s00 Ab0465s00
	 * 
	 * @param ab0465s00
	 *            the ab 0465 s 00
	 * @return the documento aperturas
	 */
	@Transactional(rollbackFor = Throwable.class)
	public DocumentoAperturas update(DocumentoAperturas ab0465s00) {
		return this.ab0465s00Dao.update(ab0465s00);
	}

	/**
	 * Updates a single row in the Ab0465s00 table.
	 * 
	 * ab0465s00 Ab0465s00 Ab0465s00
	 * 
	 * @param ab0465s00
	 *            the ab 0465 s 00
	 * @return the documento aperturas
	 */
	@Transactional(rollbackFor = Throwable.class)
	public DocumentoAperturas updateFilled(DocumentoAperturas ab0465s00) {
		return this.ab0465s00Dao.updateFilled(ab0465s00);
	}

	/**
	 * Finds a single row in the Ab0465s00 table.
	 * 
	 * ab0465s00 Ab0465s00 Ab0465s00
	 * 
	 * @param ab0465s00
	 *            the ab 0465 s 00
	 * @return the documento aperturas
	 */
	public DocumentoAperturas find(DocumentoAperturas ab0465s00) {
		return (DocumentoAperturas) this.ab0465s00Dao.vfind(ab0465s00);
	}

	/**
	 * Finds a single row in the Ab0465s00 table.
	 * 
	 * ab0465s00 Ab0465s00 Ab0465s00
	 * 
	 * @param ab0465s00
	 *            the ab 0465 s 00
	 * @return the documento aperturas
	 */
	public DocumentoAperturas findTemp(DocumentoAperturas ab0465s00) {
		return (DocumentoAperturas) this.docAperturasTempDao.find(ab0465s00);
	}

	/**
	 * Finds a single row in the Ab0465s00 table.
	 * 
	 * oid String DocumentoAperturas
	 * 
	 * @param oid
	 *            the oid
	 * @return the documento aperturas
	 */
	public DocumentoAperturas findByOid(String oid) {
		return (DocumentoAperturas) this.ab0465s00Dao.findByOid(oid);
	}

	/**
	 * Finds a single row in the Ab0465s00 table.
	 * 
	 * ab0465s00 Ab0465s00 Ab0465s00
	 * 
	 * @param ab0465s00
	 *            the ab 0465 s 00
	 * @return the documento aperturas
	 */
	public DocumentoAperturas findByTramite(DocumentoAperturas ab0465s00) {
		return (DocumentoAperturas) this.ab0465s00Dao.findByTramite(ab0465s00);
	}

	/**
	 * Deletes a single row in the Ab0465s00 table.
	 * 
	 * ab0465s00 Ab0465s00
	 * 
	 * @param ab0465s00
	 *            the ab 0465 s 00
	 */
	@Transactional(rollbackFor = Throwable.class)
	public void remove(DocumentoAperturas ab0465s00) {
		this.ab0465s00Dao.remove(ab0465s00);
	}

	/**
	 * Deletes a single row in the Ab0465s00 table.
	 * 
	 * ab0465s00 Ab0465s00
	 * 
	 * @param ab0465s00
	 *            the ab 0465 s 00
	 */
	@Transactional(rollbackFor = Throwable.class)
	public void removeTemp(DocumentoAperturas ab0465s00) {
		this.docAperturasTempDao.remove(ab0465s00);
	}

	/**
	 * Removes a single row in the Ab0465stemp table.
	 * 
	 * ab0465stemp Ab0465stemp
	 * 
	 * @param ab0465stemp
	 *            the ab 0465 stemp
	 */
	@Transactional(rollbackFor = Throwable.class)
	public void removeTempByIdApertura(DocumentoAperturas ab0465stemp) {
		this.docAperturasTempDao.removeByIdApertura(ab0465stemp);
	}

	/**
	 * Finds a list of rows in the Ab0465s00 table.
	 * 
	 * ab0465s00 Ab0465s00 jqGridRequestDto JQGridRequestDto List<Ab0465s00>
	 * 
	 * @param ab0465s00
	 *            the ab 0465 s 00
	 * @param jqGridRequestDto
	 *            the jq grid request dto
	 * @return the list
	 */
	public List<DocumentoAperturas> findAll(DocumentoAperturas ab0465s00,
			JQGridRequestDto jqGridRequestDto) {
		return (List<DocumentoAperturas>) this.ab0465s00Dao.vfindAll(ab0465s00,
				jqGridRequestDto);
	}

	/**
	 * Finds a list of rows in the Ab0465s00 table.
	 * 
	 * ab0465s00 Ab0465s00
	 * 
	 * List<Ab0465s00>
	 * 
	 * @param ab0465s00
	 *            the ab 0465 s 00
	 * @return the list
	 */
	public List<DocumentoAperturas> findAllAperturaTipo(
			DocumentoAperturas ab0465s00) {
		return (List<DocumentoAperturas>) this.ab0465s00Dao
				.buscarDocumentosAperturasTipo(ab0465s00);
	}

	/**
	 * Finds a list of rows in the Ab0465s00 table.
	 * 
	 * ab0465s00 Ab0465s00
	 * 
	 * List<Ab0465s00>
	 * 
	 * @param ab0465s00
	 *            the ab 0465 s 00
	 * @return the list
	 */
	public List<DocumentoAperturas> findAllAperturaTipoTemp(
			DocumentoAperturas ab0465s00) {
		return (List<DocumentoAperturas>) this.docAperturasTempDao
				.buscarDocumentosAperturasTempTipo(ab0465s00);
	}

	/**
	 * Finds a list of rows in the Ab0465s00 table.
	 * 
	 * ab0465s00 Ab0465s00
	 * 
	 * List<Ab0465s00>
	 * 
	 * @param ab0465s00
	 *            the ab 0465 s 00
	 * @return the list
	 */
	public List<DocumentoAperturas> findAllAperturaInspeccion(
			DocumentoAperturas ab0465s00) {
		return (List<DocumentoAperturas>) this.docAperturasTempDao
				.buscarDocumentosAperturasInspeccion(ab0465s00);
	}

	/**
	 * Busca documentos con el mismo nombre de fichero (sin tener en cuenta
	 * mayúsculas/minúsculas ni la extensión).
	 * 
	 * documento SolicDocAperturas List<SolicDocAperturas>
	 * 
	 * @param documento
	 *            the documento
	 * @return the list
	 */
	public List<DocumentoAperturas> buscarDocumentosAperturasTempIdApe(
			DocumentoAperturas documento) {
		return this.docAperturasTempDao
				.buscarDocumentosAperturasTempIdApe(documento);
	}

	/**
	 * Finds rows in the Ab0465s00 table using like.
	 * 
	 * ab0465s00 Ab0465s00 jqGridRequestDto JQGridRequestDto startsWith Boolean
	 * List<Ab0465s00>
	 * 
	 * @param ab0465s00
	 *            the ab 0465 s 00
	 * @param jqGridRequestDto
	 *            the jq grid request dto
	 * @param startsWith
	 *            the starts with
	 * @return the list
	 */
	public List<DocumentoAperturas> findAllLike(DocumentoAperturas ab0465s00,
			JQGridRequestDto jqGridRequestDto, Boolean startsWith) {
		return (List<DocumentoAperturas>) this.ab0465s00Dao.findAllLike(
				ab0465s00, jqGridRequestDto, startsWith);
	}

	/*
	 * OPERACIONES RUP_TABLE
	 */

	/**
	 * Filter method in the Ab0465s00 table.
	 * 
	 * filterAb0465s00 Ab0465s00 jqGridRequestDto JQGridRequestDto startsWith
	 * Boolean JQGridResponseDto<Ab0465s00>
	 * 
	 * @param filterAb0465s00
	 *            the filter ab 0465 s 00
	 * @param jqGridRequestDto
	 *            the jq grid request dto
	 * @param startsWith
	 *            the starts with
	 * @return the JQ grid response dto
	 */
	public JQGridResponseDto<DocumentoAperturas> filter(
			DocumentoAperturas filterAb0465s00,
			JQGridRequestDto jqGridRequestDto, Boolean startsWith) {
		List<DocumentoAperturas> listaAb0465s00 = this.ab0465s00Dao
				.findAllLike(filterAb0465s00, jqGridRequestDto, false);
		Long recordNum = this.ab0465s00Dao.findAllLikeCount(
				filterAb0465s00 != null ? filterAb0465s00
						: new DocumentoAperturas(), false);
		if (jqGridRequestDto.getMultiselection().getSelectedIds() != null) {
			List<TableRowDto<DocumentoAperturas>> reorderSelection = this.ab0465s00Dao
					.reorderSelection(filterAb0465s00, jqGridRequestDto,
							startsWith);
			return new JQGridResponseDto<DocumentoAperturas>(jqGridRequestDto,
					recordNum, listaAb0465s00, reorderSelection);
		}
		return new JQGridResponseDto<DocumentoAperturas>(jqGridRequestDto,
				recordNum, listaAb0465s00);
	}

	/**
	 * Searches rows in the Ab0465s00 table.
	 * 
	 * filterAb0465s00 Ab0465s00 searchAb0465s00 Ab0465s00 jqGridRequestDto
	 * JQGridRequestDto startsWith Boolean List<TableRowDto<Ab0465s00>>
	 * 
	 * @param filterAb0465s00
	 *            the filter ab 0465 s 00
	 * @param searchAb0465s00
	 *            the search ab 0465 s 00
	 * @param jqGridRequestDto
	 *            the jq grid request dto
	 * @param startsWith
	 *            the starts with
	 * @return the list
	 */
	public List<TableRowDto<DocumentoAperturas>> search(
			DocumentoAperturas filterAb0465s00,
			DocumentoAperturas searchAb0465s00,
			JQGridRequestDto jqGridRequestDto, Boolean startsWith) {
		return this.ab0465s00Dao.search(filterAb0465s00, searchAb0465s00,
				jqGridRequestDto, startsWith);
	}

	/**
	 * Reorder the selection made in Ab0465s00 table.
	 * 
	 * filterAb0465s00 Ab0465s00 jqGridRequestDto JQGridRequestDto startsWith
	 * Boolean Object
	 * 
	 * @param filterAb0465s00
	 *            the filter ab 0465 s 00
	 * @param jqGridRequestDto
	 *            the jq grid request dto
	 * @param startsWith
	 *            the starts with
	 * @return the object
	 */
	public Object reorderSelection(DocumentoAperturas filterAb0465s00,
			JQGridRequestDto jqGridRequestDto, Boolean startsWith) {
		return this.ab0465s00Dao.reorderSelection(filterAb0465s00,
				jqGridRequestDto, startsWith);
	}

	/**
	 * Sube fichero PIF.
	 * 
	 * datosFichero subeFicheroPIF rutaFichero String nombreFichero String
	 * preservaName boolean DocumentoAperturas
	 * 
	 * @param datosFichero
	 *            the datos fichero
	 * @param rutaFichero
	 *            the ruta fichero
	 * @param nombreFichero
	 *            the nombre fichero
	 * @param preservaName
	 *            the preserva name
	 * @return the documento aperturas
	 * @throws AB04BException
	 *             the AB 04 B exception
	 */
	@Override()
	public DocumentoAperturas subeFicheroPIF(byte[] datosFichero,
			String rutaFichero, String nombreFichero, boolean preservaName)
			throws AB04BException {
		try {
			DocumentoAperturas salida = new DocumentoAperturas();

			StringBuilder pathXml = new StringBuilder();
			pathXml.append(rutaFichero);
			pathXml.append(nombreFichero);

			// subimos fichero a la zona PIF
			String resultado = this.pifService.uploadDocument(
					new ByteArrayInputStream(datosFichero), pathXml.toString(),
					false);

			salida.setNombreDoc065(this.obtieneNombreFichero(resultado));
			salida.setRutaPif065(resultado);

			return salida;
		} catch (Exception e) {
			throw new AB04BException(e, e.getMessage());
		}
	}

	/**
	 * Borrar documento.
	 * 
	 * codDocumento Long temp boolean HashMap<String, String>
	 * 
	 * @param codDocumento
	 *            the cod documento
	 * @param temp
	 *            the temp
	 * @return the hash map
	 * @throws AB04BException
	 *             the AB 04 B exception
	 */
	@Override()
	public HashMap<String, String> borrarDocumento(Long codDocumento,
			boolean temp) throws AB04BException {

		try {
			HashMap<String, String> objetoRetorno = new HashMap<String, String>();
			String mensajeError = "";

			try {
				// recuperamos datos tramite
				DocumentoAperturas documentoTramite = new DocumentoAperturas();

				if (temp) {
					documentoTramite = this.docAperturasTempDao
							.find(new DocumentoAperturas(codDocumento));
				} else {
					documentoTramite = this.ab0465s00Dao
							.find(new DocumentoAperturas(codDocumento));
				}

				if (documentoTramite != null) {
					String rutaPIF = documentoTramite.getRutaPif065();
					this.pifService.deleteDocument(rutaPIF);

					// borramos registro
					if (temp) {
						this.docAperturasTempDao.remove(documentoTramite);
					} else {
						this.ab0465s00Dao.remove(documentoTramite);
					}

				}

			} catch (Exception ex) {
				mensajeError = "Error: " + ex.getMessage();
			}

			objetoRetorno.put("error", mensajeError);

			return objetoRetorno;
		} catch (Exception e) {
			throw new AB04BException(e, e.getMessage());
		}
	}

	/**
	 * Obtiene nombre fichero.
	 * 
	 * rutaNombreFichero String String
	 * 
	 * @param rutaNombreFichero
	 *            the ruta nombre fichero
	 * @return the string
	 */
	private String obtieneNombreFichero(String rutaNombreFichero) {

		String nombreFichero = rutaNombreFichero;

		ArrayList<String> partesRuta = new ArrayList<String>(
				Arrays.asList(rutaNombreFichero.split("/")));

		if (partesRuta != null && partesRuta.size() > 0) {
			nombreFichero = partesRuta.get(partesRuta.size() - 1);
		}
		return nombreFichero;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * com.ejie.ab04b.service.DocumentoAperturasService#addDocumentosTemp(java
	 * .util.List, java.lang.String, java.lang.Long)
	 */
	public void addDocumentosTemp(List<DocumentEvent> documents,
			String fechaCreacion, Long idTramite) {

		for (DocumentEvent document : documents) {
			// Solo se adjuntaron los que vienen con la etiqueta <sourceName>
			if (!Utilities.getInstance().isEmpty(document.getSourceName())) {

				DocumentoAperturas docNuevo = new DocumentoAperturas();
				docNuevo.setTramiteAperturas(new TramiteAperturas(idTramite));
				docNuevo.setOrigen065(Constantes.DOCUMENTO_ORIGEN_CIUDADANO);
				docNuevo.setFechaDoc065(PlateaTramitacionUtils.getInstance()
						.parsearTimestampPlatea(fechaCreacion));
				docNuevo.setNombreDoc065(document.getSourceName());

				// TODO OID se actualiza despues????
				// docNuevo.setOidDokusi065(document.getOid());

				docNuevo.setRutaPif065(document.getLocation());
				docNuevo.setFormatoAport065(Constantes.FORMATO_APORTACION_ELECTRONICO);

				// Obtenemos el tipo de documento
				String[] partesRolDocumento = document.getRoleId().split(
						"\\".concat(Constantes.SEPARADOR_PUNTO));
				TipoDocumento tipoDocumento = new TipoDocumento();
				if (partesRolDocumento != null && partesRolDocumento.length > 0) {
					tipoDocumento.setTipoDokusi091(partesRolDocumento[0]);
					tipoDocumento
							.setAsuntoDokusi091(partesRolDocumento[ConstantesNum.NUM_2]);
				}
				tipoDocumento = this.tipoDocumentoService
						.findByTipoAsuntoDocumental(tipoDocumento);
				docNuevo.setTipoDocumento(tipoDocumento);

				this.ab0465s00Dao.add(docNuevo);
			}
		}

	}
}
