package com.ejie.ab04b.service;

import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Arrays;
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.DocumentoOS2CustomDao;
import com.ejie.ab04b.dao.temp.DocumentosOS2TempDao;
import com.ejie.ab04b.exception.AB04BException;
import com.ejie.ab04b.model.DocumentoOS2;
import com.ejie.ab04b.model.TipoDocumento;
import com.ejie.ab04b.model.TramiteOS2;
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;

/**
 * Ab0494s00ServiceImpl generated by UDA, 05-Apr-2017 09:34:34.
 * 
 * @author UDA
 */

@Service(value = "ab0494s00Service")
public class DocumentoOS2ServiceImpl implements DocumentoOS2Service {

	@Autowired()
	private DocumentoOS2CustomDao ab0494s00Dao;
	@Autowired()
	private DocumentosOS2TempDao documentosOS2TempDao;
	@Autowired()
	private TipoDocumentoService tipoDocumentoService;

	@Autowired
	private PifService pifService;

	/**
	 * Inserts a single row in the Ab0494s00 table.
	 * 
	 * ab0494s00 Ab0494s00 Ab0494s00
	 * 
	 * @param ab0494s00
	 *            the ab 0494 s 00
	 * @return the documento OS 2
	 */
	@Transactional(rollbackFor = Throwable.class)
	public DocumentoOS2 add(DocumentoOS2 ab0494s00) {
		return this.ab0494s00Dao.add(ab0494s00);
	}

	/**
	 * Inserts a single row in the Ab0494s00 table.
	 * 
	 * ab0465s00 Ab0494s00 temp boolean Ab0494s00
	 * 
	 * @param ab0494s00
	 *            the ab 0494 s 00
	 * @param temp
	 *            the temp
	 * @return the documento os2
	 */
	@Transactional(rollbackFor = Throwable.class)
	public DocumentoOS2 add(DocumentoOS2 ab0494s00, boolean temp) {

		if (temp) {
			return this.documentosOS2TempDao.add(ab0494s00);
		} else {
			return this.ab0494s00Dao.add(ab0494s00);
		}
	}

	/**
	 * 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())) {

				DocumentoOS2 docNuevo = new DocumentoOS2();
				docNuevo.setTramiteOS2(new TramiteOS2(idTramite));
				docNuevo.setOrigen094(Constantes.DOCUMENTO_ORIGEN_CIUDADANO);
				docNuevo.setFechaDoc094(PlateaTramitacionUtils.getInstance()
						.parsearTimestampPlatea(fechaCreacion));
				docNuevo.setNombreDoc094(document.getSourceName());

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

				docNuevo.setRutaPif094(document.getLocation());
				docNuevo.setFormatoAport094(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.ab0494s00Dao.add(docNuevo);
			}
		}
	}

	/**
	 * Updates a single row in the Ab0494s00 table.
	 * 
	 * ab0494s00 Ab0494s00 Ab0494s00
	 * 
	 * @param ab0494s00
	 *            the ab 0494 s 00
	 * @return the documento OS 2
	 */
	@Transactional(rollbackFor = Throwable.class)
	public DocumentoOS2 update(DocumentoOS2 ab0494s00) {
		return this.ab0494s00Dao.update(ab0494s00);
	}

	/**
	 * Finds a single row in the Ab0494s00 table.
	 * 
	 * ab0494s00 Ab0494s00 Ab0494s00
	 * 
	 * @param ab0494s00
	 *            the ab 0494 s 00
	 * @return the documento OS 2
	 */
	public DocumentoOS2 find(DocumentoOS2 ab0494s00) {
		return (DocumentoOS2) this.ab0494s00Dao.vfind(ab0494s00);
	}

	/**
	 * Finds a single row in the Ab0465s00 table.
	 * 
	 * oid String DocumentoOS2
	 * 
	 * @param oid
	 *            the oid
	 * @return the documento OS 2
	 */
	public DocumentoOS2 findByOid(String oid) {
		return (DocumentoOS2) this.ab0494s00Dao.findByOid(oid);
	}

	/**
	 * Finds a single row in the Ab0465s00 table.
	 * 
	 * doc DocumentoOS2 DocumentoOS2
	 * 
	 * @param doc
	 *            the doc
	 * @return the documento OS 2
	 */
	public DocumentoOS2 findByTramite(DocumentoOS2 doc) {
		return (DocumentoOS2) this.ab0494s00Dao.findByTramite(doc);
	}

	/**
	 * Finds a single row in the Ab0494s00 table.
	 * 
	 * ab0494s00 Ab0494s00 Ab0494s00
	 * 
	 * @param ab0494s00
	 *            the ab 0494 s 00
	 * @return the documento os2
	 */
	public DocumentoOS2 findTemp(DocumentoOS2 ab0494s00) {
		return (DocumentoOS2) this.documentosOS2TempDao.find(ab0494s00);
	}

	/**
	 * Deletes a single row in the Ab0494s00 table.
	 * 
	 * ab0494s00 Ab0494s00
	 * 
	 * @param ab0494s00
	 *            the ab 0494 s 00
	 */
	@Transactional(rollbackFor = Throwable.class)
	public void remove(DocumentoOS2 ab0494s00) {
		this.ab0494s00Dao.remove(ab0494s00);
	}

	/**
	 * Deletes a single row in the Ab0427s00 table.
	 * 
	 * ab0427s00 Ab0427s00
	 * 
	 * @param ab0427s00
	 *            the ab 0427 s 00
	 */
	@Transactional(rollbackFor = Throwable.class)
	public void removeTemp(DocumentoOS2 ab0427s00) {
		this.documentosOS2TempDao.remove(ab0427s00);
	}

	/**
	 * Deletes a single row in the Ab0427s00 table.
	 * 
	 * ab0427s00 Ab0427s00
	 * 
	 * @param ab0427s00
	 *            the ab 0427 s 00
	 */
	@Transactional(rollbackFor = Throwable.class)
	public void removeTempByApertura(DocumentoOS2 ab0427s00) {
		this.documentosOS2TempDao.removeByIdApertura(ab0427s00);
	}

	/**
	 * Finds a list of rows in the Ab0494s00 table.
	 * 
	 * ab0494s00 Ab0494s00 jqGridRequestDto JQGridRequestDto List<Ab0494s00>
	 * 
	 * @param ab0494s00
	 *            the ab 0494 s 00
	 * @param jqGridRequestDto
	 *            the jq grid request dto
	 * @return the list
	 */
	public List<DocumentoOS2> findAll(DocumentoOS2 ab0494s00,
			JQGridRequestDto jqGridRequestDto) {
		return (List<DocumentoOS2>) this.ab0494s00Dao.vfindAll(ab0494s00,
				jqGridRequestDto);
	}

	/**
	 * Finds rows in the Ab0494s00 table using like.
	 * 
	 * ab0494s00 Ab0494s00 jqGridRequestDto JQGridRequestDto startsWith Boolean
	 * List<Ab0494s00>
	 * 
	 * @param ab0494s00
	 *            the ab 0494 s 00
	 * @param jqGridRequestDto
	 *            the jq grid request dto
	 * @param startsWith
	 *            the starts with
	 * @return the list
	 */
	public List<DocumentoOS2> findAllLike(DocumentoOS2 ab0494s00,
			JQGridRequestDto jqGridRequestDto, Boolean startsWith) {
		return (List<DocumentoOS2>) this.ab0494s00Dao.findAllLike(ab0494s00,
				jqGridRequestDto, startsWith);
	}

	/*
	 * OPERACIONES RUP_TABLE
	 */

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

	/**
	 * Searches rows in the Ab0494s00 table.
	 * 
	 * filterAb0494s00 Ab0494s00 searchAb0494s00 Ab0494s00 jqGridRequestDto
	 * JQGridRequestDto startsWith Boolean List<TableRowDto<Ab0494s00>>
	 * 
	 * @param filterAb0494s00
	 *            the filter ab 0494 s 00
	 * @param searchAb0494s00
	 *            the search ab 0494 s 00
	 * @param jqGridRequestDto
	 *            the jq grid request dto
	 * @param startsWith
	 *            the starts with
	 * @return the list
	 */
	public List<TableRowDto<DocumentoOS2>> search(DocumentoOS2 filterAb0494s00,
			DocumentoOS2 searchAb0494s00, JQGridRequestDto jqGridRequestDto,
			Boolean startsWith) {
		return this.ab0494s00Dao.search(filterAb0494s00, searchAb0494s00,
				jqGridRequestDto, startsWith);
	}

	/**
	 * Reorder the selection made in Ab0494s00 table.
	 * 
	 * filterAb0494s00 Ab0494s00 jqGridRequestDto JQGridRequestDto startsWith
	 * Boolean Object
	 * 
	 * @param filterAb0494s00
	 *            the filter ab 0494 s 00
	 * @param jqGridRequestDto
	 *            the jq grid request dto
	 * @param startsWith
	 *            the starts with
	 * @return the object
	 */
	public Object reorderSelection(DocumentoOS2 filterAb0494s00,
			JQGridRequestDto jqGridRequestDto, Boolean startsWith) {
		return this.ab0494s00Dao.reorderSelection(filterAb0494s00,
				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 DocumentoOS2 subeFicheroPIF(byte[] datosFichero, String rutaFichero,
			String nombreFichero, boolean preservaName) throws AB04BException {
		try {
			DocumentoOS2 salida = new DocumentoOS2();

			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.setNombreDoc094(this.obtieneNombreFichero(resultado));
			salida.setRutaPif094(resultado);

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

	/**
	 * Updates a single row in the Ab0465s00 table.
	 * 
	 * ab0494s00 DocumentoOS2 DocumentoOS2
	 * 
	 * @param ab0494s00
	 *            the ab 0494 s 00
	 * @return the documento OS 2
	 */
	@Transactional(rollbackFor = Throwable.class)
	public DocumentoOS2 updateFilled(DocumentoOS2 ab0494s00) {
		return this.ab0494s00Dao.updateFilled(ab0494s00);
	}

	/**
	 * 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.DocumentoOS2Service#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());
		}
	}
}
