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.DocumentoOS3CustomDao;
import com.ejie.ab04b.dao.temp.DocumentosOS3TempDao;
import com.ejie.ab04b.exception.AB04BException;
import com.ejie.ab04b.model.DocumentoOS3;
import com.ejie.ab04b.model.TipoDocumento;
import com.ejie.ab04b.model.TramiteOS3;
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;

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

@Service(value = "ab0497s00Service")
public class DocumentoOS3ServiceImpl implements DocumentoOS3Service {

	@Autowired()
	private DocumentoOS3CustomDao ab0497s00Dao;
	@Autowired()
	private DocumentosOS3TempDao documentosOS3TempDao;
	@Autowired()
	private TipoDocumentoService tipoDocumentoService;

	@Autowired
	private PifService pifService;

	/**
	 * Inserts a single row in the Ab0497s00 table.
	 * 
	 * ab0497s00 Ab0497s00 Ab0497s00
	 * 
	 * @param ab0497s00
	 *            the ab 0497 s 00
	 * @return the documento OS 3
	 */
	@Transactional(rollbackFor = Throwable.class)
	public DocumentoOS3 add(DocumentoOS3 ab0497s00) {
		return this.ab0497s00Dao.add(ab0497s00);
	}

	/**
	 * Inserts a single row in the Ab0494s00 table.
	 * 
	 * ab0497s00 Ab0497s00 temp boolean Ab0497s00
	 * 
	 * @param ab0497s00
	 *            the ab 0497 s 00
	 * @param temp
	 *            the temp
	 * @return the documento os3
	 */
	@Transactional(rollbackFor = Throwable.class)
	public DocumentoOS3 add(DocumentoOS3 ab0497s00, boolean temp) {

		if (temp) {
			return this.documentosOS3TempDao.add(ab0497s00);
		} else {
			return this.ab0497s00Dao.add(ab0497s00);
		}
	}

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

				DocumentoOS3 docNuevo = new DocumentoOS3();
				docNuevo.setTramiteOS3(new TramiteOS3(idTramite));
				docNuevo.setOrigen097(Constantes.DOCUMENTO_ORIGEN_CIUDADANO);
				docNuevo.setFechaDoc097(PlateaTramitacionUtils.getInstance()
						.parsearTimestampPlatea(fechaCreacion));
				docNuevo.setNombreDoc097(document.getSourceName());

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

				docNuevo.setRutaPif097(document.getLocation());
				docNuevo.setFormatoAport097(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.ab0497s00Dao.add(docNuevo);
			}
		}
	}

	/**
	 * Updates a single row in the Ab0497s00 table.
	 * 
	 * ab0497s00 Ab0497s00 Ab0497s00
	 * 
	 * @param ab0497s00
	 *            the ab 0497 s 00
	 * @return the documento OS 3
	 */
	@Transactional(rollbackFor = Throwable.class)
	public DocumentoOS3 update(DocumentoOS3 ab0497s00) {
		return this.ab0497s00Dao.update(ab0497s00);
	}

	/**
	 * Finds a single row in the Ab0497s00 table.
	 * 
	 * ab0497s00 Ab0497s00 Ab0497s00
	 * 
	 * @param ab0497s00
	 *            the ab 0497 s 00
	 * @return the documento OS 3
	 */
	public DocumentoOS3 find(DocumentoOS3 ab0497s00) {
		return (DocumentoOS3) this.ab0497s00Dao.vfind(ab0497s00);
	}

	/**
	 * Finds a single row in the Ab0497s00 table.
	 * 
	 * oid String DocumentoAperturas
	 * 
	 * @param oid
	 *            the oid
	 * @return the documento OS 3
	 */
	public DocumentoOS3 findByOid(String oid) {
		return (DocumentoOS3) this.ab0497s00Dao.findByOid(oid);
	}

	/**
	 * Finds a single row in the Ab0497s00 table.
	 * 
	 * doc DocumentoOS3 DocumentoOS3
	 * 
	 * @param doc
	 *            the doc
	 * @return the documento OS 3
	 */
	public DocumentoOS3 findByTramite(DocumentoOS3 doc) {
		return (DocumentoOS3) this.ab0497s00Dao.findByTramite(doc);
	}

	/**
	 * Finds a single row in the Ab0497s00 table.
	 * 
	 * ab0494s00 Ab0497s00 Ab0497s00
	 * 
	 * @param ab0497s00
	 *            the ab 0497 s 00
	 * @return the documento os3
	 */
	public DocumentoOS3 findTemp(DocumentoOS3 ab0497s00) {
		return (DocumentoOS3) this.documentosOS3TempDao.find(ab0497s00);
	}

	/**
	 * Deletes a single row in the Ab0497s00 table.
	 * 
	 * ab0497s00 Ab0497s00
	 * 
	 * @param ab0497s00
	 *            the ab 0497 s 00
	 */
	@Transactional(rollbackFor = Throwable.class)
	public void remove(DocumentoOS3 ab0497s00) {
		this.ab0497s00Dao.remove(ab0497s00);
	}

	/**
	 * Deletes a single row in the Ab0429s00 table.
	 * 
	 * ab0429s00 Ab0429s00
	 * 
	 * @param ab0429s00
	 *            the ab 0429 s 00
	 */
	@Transactional(rollbackFor = Throwable.class)
	public void removeTemp(DocumentoOS3 ab0429s00) {
		this.documentosOS3TempDao.remove(ab0429s00);
	}

	/**
	 * Deletes a single row in the Ab0427s00 table.
	 * 
	 * ab0429s00 Ab0429s00
	 * 
	 * @param ab0429s00
	 *            the ab 0429 s 00
	 */
	@Transactional(rollbackFor = Throwable.class)
	public void removeTempByApertura(DocumentoOS3 ab0429s00) {
		this.documentosOS3TempDao.removeByIdApertura(ab0429s00);
	}

	/**
	 * Finds a list of rows in the Ab0497s00 table.
	 * 
	 * ab0497s00 Ab0497s00 jqGridRequestDto JQGridRequestDto List<Ab0497s00>
	 * 
	 * @param ab0497s00
	 *            the ab 0497 s 00
	 * @param jqGridRequestDto
	 *            the jq grid request dto
	 * @return the list
	 */
	public List<DocumentoOS3> findAll(DocumentoOS3 ab0497s00,
			JQGridRequestDto jqGridRequestDto) {
		return (List<DocumentoOS3>) this.ab0497s00Dao.vfindAll(ab0497s00,
				jqGridRequestDto);
	}

	/**
	 * Finds rows in the Ab0497s00 table using like.
	 * 
	 * ab0497s00 Ab0497s00 jqGridRequestDto JQGridRequestDto startsWith Boolean
	 * List<Ab0497s00>
	 * 
	 * @param ab0497s00
	 *            the ab 0497 s 00
	 * @param jqGridRequestDto
	 *            the jq grid request dto
	 * @param startsWith
	 *            the starts with
	 * @return the list
	 */
	public List<DocumentoOS3> findAllLike(DocumentoOS3 ab0497s00,
			JQGridRequestDto jqGridRequestDto, Boolean startsWith) {
		return (List<DocumentoOS3>) this.ab0497s00Dao.findAllLike(ab0497s00,
				jqGridRequestDto, startsWith);
	}

	/*
	 * OPERACIONES RUP_TABLE
	 */

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

	/**
	 * Searches rows in the Ab0497s00 table.
	 * 
	 * filterAb0497s00 Ab0497s00 searchAb0497s00 Ab0497s00 jqGridRequestDto
	 * JQGridRequestDto startsWith Boolean List<TableRowDto<Ab0497s00>>
	 * 
	 * @param filterAb0497s00
	 *            the filter ab 0497 s 00
	 * @param searchAb0497s00
	 *            the search ab 0497 s 00
	 * @param jqGridRequestDto
	 *            the jq grid request dto
	 * @param startsWith
	 *            the starts with
	 * @return the list
	 */
	public List<TableRowDto<DocumentoOS3>> search(DocumentoOS3 filterAb0497s00,
			DocumentoOS3 searchAb0497s00, JQGridRequestDto jqGridRequestDto,
			Boolean startsWith) {
		return this.ab0497s00Dao.search(filterAb0497s00, searchAb0497s00,
				jqGridRequestDto, startsWith);
	}

	/**
	 * Reorder the selection made in Ab0497s00 table.
	 * 
	 * filterAb0497s00 Ab0497s00 jqGridRequestDto JQGridRequestDto startsWith
	 * Boolean Object
	 * 
	 * @param filterAb0497s00
	 *            the filter ab 0497 s 00
	 * @param jqGridRequestDto
	 *            the jq grid request dto
	 * @param startsWith
	 *            the starts with
	 * @return the object
	 */
	public Object reorderSelection(DocumentoOS3 filterAb0497s00,
			JQGridRequestDto jqGridRequestDto, Boolean startsWith) {
		return this.ab0497s00Dao.reorderSelection(filterAb0497s00,
				jqGridRequestDto, startsWith);
	}

	/**
	 * Updates a single row in the Ab0465s00 table.
	 * 
	 * ab0497s00 DocumentoOS3 DocumentoOS3
	 * 
	 * @param ab0497s00
	 *            the ab 0497 s 00
	 * @return the documento OS 3
	 */
	@Transactional(rollbackFor = Throwable.class)
	public DocumentoOS3 updateFilled(DocumentoOS3 ab0497s00) {
		return this.ab0497s00Dao.updateFilled(ab0497s00);
	}

	/**
	 * Sube fichero PIF.
	 * 
	 * datosFichero subeFicheroPIF rutaFichero String nombreFichero String
	 * preservaName boolean DocumentoOs3
	 * 
	 * @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 DocumentoOS3 subeFicheroPIF(byte[] datosFichero, String rutaFichero,
			String nombreFichero, boolean preservaName) throws AB04BException {
		try {
			DocumentoOS3 salida = new DocumentoOS3();

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

			return salida;
		} 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.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());
		}
	}
}
