package com.ejie.ab79.service.actuaciones;

import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.ejie.ab79.clientesWS.ab61WebService.Ab61Exception;
import com.ejie.ab79.dao.DocumentosSubidosDao;
import com.ejie.ab79.dao.actuaciones.ActuacionesDao;
import com.ejie.ab79.dao.actuaciones.RelActDocDao;
import com.ejie.ab79.dao.expedientes.DatosTercerosDao;
import com.ejie.ab79.model.DocumentosSubidos;
import com.ejie.ab79.model.REST.servicioWeb.Actuacion;
import com.ejie.ab79.model.actuaciones.Actuaciones;
import com.ejie.ab79.model.inspecciones.Inspecciones;
import com.ejie.ab79.webservice.adaptadores.ab61WebServiceAdaptador;
import com.ejie.x38.dto.JerarquiaDto;
import com.ejie.x38.dto.TableRequestDto;
import com.ejie.x38.dto.TableResponseDto;
import com.ejie.x38.dto.TableRowDto;

/**
 * ActuacionesServiceImpl  
 * 
 *  
 */

@Service(value = "actuacionesService")
public class ActuacionesServiceImpl implements ActuacionesService {

	private static final Logger logger = LoggerFactory.getLogger(ActuacionesServiceImpl.class);

	@Autowired
	private ActuacionesDao actuacionesDao;

	@Autowired
	private RelActDocDao relActDocDao;

	@Autowired
	private ab61WebServiceAdaptador ab61WebServiceAdaptadorService;

	@Autowired
	private DatosTercerosDao datosTercerosDao;

	@Autowired
	private DocumentosSubidosDao documentosSubidosDao;

	/**
	 * Inserts a single row in the Actuaciones table.
	 *
	 * @param actuaciones
	 *            Actuaciones
	 * @return Actuaciones
	 */
	@Override
	@Transactional(rollbackFor = Throwable.class)
	public Actuaciones add(Actuaciones actuaciones) {

		/*
		 * En un alta nunca tendremos un idTercero, si se meten datos, se
		 * inserta en DATOS_TERCEROS
		 */
		if (null != actuaciones && null != actuaciones.getCompareciente()
				&& (null != actuaciones.getCondicionCompareciente()
						|| null != actuaciones.getObservacionesCompareciente()
						|| null != actuaciones.getCompareciente().getTipoDocumento().getIdTipoDocumento()
						|| null != actuaciones.getCompareciente().getDocumento()
						|| null != actuaciones.getCompareciente().getNombre()
						|| null != actuaciones.getCompareciente().getApellido1()
						|| null != actuaciones.getCompareciente().getApellido2()
						|| null != actuaciones.getCompareciente().getIdioma())) {

			actuaciones.getCompareciente().setUsuarioRegistro(actuaciones.getUsuarioRegistro());
			actuaciones.setCompareciente(this.datosTercerosDao.add(actuaciones.getCompareciente()));
		}

		return this.actuacionesDao.add(actuaciones);
	}

	/**
	 * Updates a single row in the Actuaciones table.
	 *
	 * @param actuaciones
	 *            Actuaciones
	 * @return Actuaciones
	 */
	@Override
	@Transactional(rollbackFor = Throwable.class)
	public Actuaciones update(Actuaciones actuaciones) {

		Integer idTerceroCompareciente = 0;
		if (null != actuaciones && null != actuaciones.getCompareciente()
				&& (null != actuaciones.getCondicionCompareciente()
						|| null != actuaciones.getObservacionesCompareciente()
						|| (null != actuaciones.getCompareciente().getTipoDocumento()
								&& null != actuaciones.getCompareciente().getTipoDocumento().getIdTipoDocumento())
						|| null != actuaciones.getCompareciente().getDocumento()
						|| null != actuaciones.getCompareciente().getNombre()
						|| null != actuaciones.getCompareciente().getApellido1()
						|| null != actuaciones.getCompareciente().getApellido2()
						|| null != actuaciones.getCompareciente().getIdioma())) {
			/* Si ya existe el compareciente se actualiza, si no se inserta */
			if (null != actuaciones.getCompareciente().getIdTercero()) {
				actuaciones.getCompareciente().setUsuarioUltmodificacion(actuaciones.getUsuarioUltmodificacion());
				actuaciones.setCompareciente(this.datosTercerosDao.update(actuaciones.getCompareciente()));
			} else {
				actuaciones.getCompareciente().setUsuarioRegistro(actuaciones.getUsuarioUltmodificacion());
				actuaciones.setCompareciente(this.datosTercerosDao.add(actuaciones.getCompareciente()));
			}
		} else if (null != actuaciones && null != actuaciones.getCompareciente()
				&& null != actuaciones.getCompareciente().getIdTercero()) {
			/* Si se elimina el Compareciente, se borra de DATOS_TERCERO */
			idTerceroCompareciente = actuaciones.getCompareciente().getIdTercero();
			actuaciones.getCompareciente().setIdTercero(null);
		}

		Actuaciones actuacionesAux = this.actuacionesDao.update(actuaciones);

		if (idTerceroCompareciente != 0) {
			this.datosTercerosDao.remove(idTerceroCompareciente);
		}

		return actuacionesAux;
	}

	/**
	 * Finds a single row in the Actuaciones table.
	 *
	 * @param actuaciones
	 *            Actuaciones
	 * @return Actuaciones
	 */
	@Override
	public Actuaciones find(Actuaciones actuaciones) {
		return this.actuacionesDao.find(actuaciones);
	}

	@Override
	public List<Actuaciones> findByInspeccion(Inspecciones inspeccion) {
		return this.actuacionesDao.findByInspeccion(inspeccion);
	}

	/**
	 * Deletes a single row in the Actuaciones table.
	 *
	 * @param actuaciones
	 *            Actuaciones
	 */
	@Override
	@Transactional(rollbackFor = Throwable.class)
	public void remove(Actuaciones actuaciones) {

		/* Para buscar el idTerceroCompareciente */
		Actuaciones actuacionesAux = this.actuacionesDao.find(actuaciones);

		this.actuacionesDao.remove(actuacionesAux);

		/* Eliminar el compareciente */
		if (null != actuacionesAux && null != actuacionesAux.getCompareciente()
				&& null != actuacionesAux.getCompareciente().getIdTercero()) {
			this.datosTercerosDao.remove(actuacionesAux.getCompareciente().getIdTercero());
		}
	}

	@Override
	@Transactional(rollbackFor = Throwable.class)
	public void removeByInspeccion(Inspecciones inspeccion) {
		this.actuacionesDao.removeByInspeccion(inspeccion);
	}

	/**
	 * Finds a list of rows in the Actuaciones table.
	 *
	 * @param actuaciones
	 *            Actuaciones
	 * @param tableRequestDto
	 *            TableRequestDto
	 * @return List<Actuaciones>
	 */
	@Override
	public List<Actuaciones> findAll(Actuaciones actuaciones, TableRequestDto tableRequestDto) {
		return this.actuacionesDao.findAll(actuaciones, tableRequestDto);
	}

	/**
	 * Finds rows in the Actuaciones table using like.
	 *
	 * @param actuaciones
	 *            Actuaciones
	 * @param tableRequestDto
	 *            TableRequestDto
	 * @param startsWith
	 *            Boolean
	 * @return List<Actuaciones>
	 */
	@Override
	public List<Actuaciones> findAllLike(Actuaciones actuaciones, TableRequestDto tableRequestDto, Boolean startsWith) {
		return this.actuacionesDao.findAllLike(actuaciones, tableRequestDto, startsWith);
	}

	@Override
	public List<Actuacion> findActuacionesREST(Integer idInspeccion) {
		return this.actuacionesDao.findActuacionesREST(idInspeccion);
	}

	/*
	 * OPERACIONES RUP_TABLE
	 */

	/**
	 * Removes rows from the Actuaciones table.
	 *
	 * @param filterActuaciones
	 *            Actuaciones
	 * @param tableRequestDto
	 *            TableRequestDto
	 * @param startsWith
	 *            Boolean
	 */
	@Override
	public void removeMultiple(Actuaciones filterActuaciones, TableRequestDto tableRequestDto, Boolean startsWith) {
		this.actuacionesDao.removeMultiple(filterActuaciones, tableRequestDto, startsWith);
	}

	/**
	 * Filter method in the Actuaciones table.
	 *
	 * @param filterActuaciones
	 *            Actuaciones
	 * @param tableRequestDto
	 *            TableRequestDto
	 * @param startsWith
	 *            Boolean
	 * @return TableResponseDto<Actuaciones>
	 */
	@Override
	public TableResponseDto<Actuaciones> filter(Actuaciones filterActuaciones, TableRequestDto tableRequestDto,
			Boolean startsWith) {

		this.fncReordenarActuaciones(tableRequestDto);

		List<Actuaciones> listaActuaciones = this.actuacionesDao.findAllLike(filterActuaciones, tableRequestDto, false);

		for (Actuaciones actuacion : listaActuaciones) {
			int numeroDocumentosAsociados = this.actuacionesDao.numeroDocumentosAsociados(actuacion);
			actuacion.setNumeroDocumentos(numeroDocumentosAsociados);
		}

		Long recordNum = this.actuacionesDao
				.findAllLikeCount(filterActuaciones != null ? filterActuaciones : new Actuaciones(), false);

		TableResponseDto<Actuaciones> usuarioDto = new TableResponseDto<Actuaciones>(tableRequestDto, recordNum,
				listaActuaciones);

		if (tableRequestDto.getMultiselection().getSelectedIds() != null) {
			List<TableRowDto<Actuaciones>> reorderSelection = this.actuacionesDao.reorderSelection(filterActuaciones,
					tableRequestDto, startsWith);
			usuarioDto.setReorderedSelection(reorderSelection);
			usuarioDto.addAdditionalParam("reorderedSelection", reorderSelection);
			usuarioDto.addAdditionalParam("selectedAll", tableRequestDto.getMultiselection().getSelectedAll());
		}
		if (tableRequestDto.getSeeker().getSelectedIds() != null) {
			tableRequestDto.setMultiselection(tableRequestDto.getSeeker());
			List<TableRowDto<Actuaciones>> reorderSeeker = this.actuacionesDao.reorderSelection(filterActuaciones,
					tableRequestDto, startsWith);
			usuarioDto.setReorderedSeeker(reorderSeeker);
			usuarioDto.addAdditionalParam("reorderedSeeker", reorderSeeker);
		}
		return usuarioDto;
	}

	/**
	 * Searches rows in the Actuaciones table.
	 *
	 * @param filterActuaciones
	 *            Actuaciones
	 * @param searchActuaciones
	 *            Actuaciones
	 * @param tableRequestDto
	 *            TableRequestDto
	 * @param startsWith
	 *            Boolean
	 * @return List<TableRowDto<Actuaciones>>
	 */
	@Override
	public List<TableRowDto<Actuaciones>> search(Actuaciones filterActuaciones, Actuaciones searchActuaciones,
			TableRequestDto tableRequestDto, Boolean startsWith) {
		return this.actuacionesDao.search(filterActuaciones, searchActuaciones, tableRequestDto, startsWith);
	}

	/**
	 * Reorder the selection made in Actuaciones table.
	 *
	 * @param filterActuaciones
	 *            Actuaciones
	 * @param tableRequestDto
	 *            TableRequestDto
	 * @param startsWith
	 *            Boolean
	 * @return Object
	 */
	@Override
	public Object reorderSelection(Actuaciones filterActuaciones, TableRequestDto tableRequestDto, Boolean startsWith) {
		return this.actuacionesDao.reorderSelection(filterActuaciones, tableRequestDto, startsWith);
	}

	/*
	 * OPERACIONES RUP_TABLE JERARQUIA
	 */

	/**
	 * Finder method in the hierarchical the Actuaciones table.
	 *
	 * @param filterActuaciones
	 *            Actuaciones
	 * @param tableRequestDto
	 *            TableRequestDto
	 * @param startsWith
	 *            Boolean
	 * @return TableResponseDto<JerarquiaDto<Actuaciones>>
	 */
	@Override
	public TableResponseDto<JerarquiaDto<Actuaciones>> jerarquia(Actuaciones filterActuaciones,
			TableRequestDto tableRequestDto, Boolean startsWith) {
		List<JerarquiaDto<Actuaciones>> listaActuaciones = this.actuacionesDao.findAllLikeJerarquia(filterActuaciones,
				tableRequestDto);
		Long recordNum = this.actuacionesDao.findAllLikeCountJerarquia(filterActuaciones, tableRequestDto);
		return new TableResponseDto<JerarquiaDto<Actuaciones>>(tableRequestDto, recordNum, listaActuaciones);
	}

	/**
	 * Finder method for siblings rows in the hierarchical the Actuaciones
	 * table.
	 *
	 * @param filterActuaciones
	 *            Actuaciones
	 * @param tableRequestDto
	 *            TableRequestDto
	 * @return TableResponseDto<JerarquiaDto<Actuaciones>>
	 */
	@Override
	public TableResponseDto<JerarquiaDto<Actuaciones>> jerarquiaChildren(Actuaciones filterActuaciones,
			TableRequestDto tableRequestDto) {
		TableResponseDto<JerarquiaDto<Actuaciones>> tableResponseDto = new TableResponseDto<JerarquiaDto<Actuaciones>>();
		tableResponseDto.addAdditionalParam(TableResponseDto.CHILDREN,
				this.actuacionesDao.findAllChild(filterActuaciones, tableRequestDto));
		return tableResponseDto;
	}

	/**
	 * Exporta Datos al clipBoard
	 *
	 */
	@Override
	public List<Actuaciones> getMultiple(Actuaciones filterActuaciones, TableRequestDto tableRequestDto,
			Boolean startsWith) {
		return this.actuacionesDao.getMultiple(filterActuaciones, tableRequestDto, startsWith);
	}

	/**
	 * Transformar los campos del ORDER BY cuando están dentro de un objeto
	 * 
	 * @param tableRequestDto
	 *            TableRequestDto
	 */
	private void fncReordenarActuaciones(TableRequestDto tableRequestDto) {

		if (tableRequestDto != null && tableRequestDto.getSidx() != null
				&& tableRequestDto.getSidx().equals("tipoActuacion.descripcionCastellano")) {
			tableRequestDto.setSidx("TIPODESCRIPCIONCASTELLANO");
		} else if (tableRequestDto != null && tableRequestDto.getSidx() != null
				&& tableRequestDto.getSidx().equals("tipoActuacion.descripcionEuskera")) {
			tableRequestDto.setSidx("TIPODESCRIPCIONEUSKERA");
		} else if (tableRequestDto != null && tableRequestDto.getSidx() != null
				&& tableRequestDto.getSidx().equals("resultadoActuacion.descripcionCastellano")) {
			tableRequestDto.setSidx("RESULTADODESCRIPCIONCASTELLANO");
		} else if (tableRequestDto != null && tableRequestDto.getSidx() != null
				&& tableRequestDto.getSidx().equals("resultadoActuacion.descripcionEuskera")) {
			tableRequestDto.setSidx("RESULTADODESCRIPCIONEUSKERA");
		}
	}

	@Transactional
	@Override
	public void eliminarActuacion(Actuaciones actuaciones) {

		List<DocumentosSubidos> listaDocumentosSubidos = this.documentosSubidosDao
				.findOidsByActuacion(actuaciones.getIdActuacion());

		for (DocumentosSubidos documentoSubido : listaDocumentosSubidos) {
			if (documentoSubido.getOidPid() != null && !"".equals(documentoSubido.getOidPid())) {
				// Eliminamos documento del PID
				try {
					this.ab61WebServiceAdaptadorService.eliminarDocumentoPid(documentoSubido.getOidPid());
				} catch (Ab61Exception e) {
					ActuacionesServiceImpl.logger.error("eliminarActuacion - ERROR: ", e);
				}
			} else {
				this.documentosSubidosDao.remove(documentoSubido);
			}
		}

		// Eliminamos los documentos de BBDD
		this.relActDocDao.removeByIdActuacion(actuaciones.getIdActuacion());

		/* Para buscar el idTerceroCompareciente */
		Actuaciones actuacionesAux = this.actuacionesDao.find(actuaciones);

		// Eliminamos la actuaci�n
		this.actuacionesDao.remove(actuacionesAux);

		/* Eliminar el compareciente */
		if (null != actuacionesAux && null != actuacionesAux.getCompareciente()
				&& null != actuacionesAux.getCompareciente().getIdTercero()) {
			this.datosTercerosDao.remove(actuacionesAux.getCompareciente().getIdTercero());
		}
	}

	@Override
	public Integer findIdByIdActuacionMovil(String idActuacionMovil) {
		return this.actuacionesDao.findIdByIdActuacionMovil(idActuacionMovil);
	}

	@Override
	public Actuaciones findMaxDateActuaciones(Integer idInspeccion) {
		return this.actuacionesDao.findMaxDateActuaciones(idInspeccion);
	}
}
