package com.ejie.ab61.service.expedientes;

import java.util.ArrayList;
import java.util.List;
import java.util.logging.Logger;

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

import com.ejie.ab61.adaptadores.X43ExpedienteElectronicoAdaptadorService;
import com.ejie.ab61.clientesWS.X43ExpedienteElectronico.TAccount;
import com.ejie.ab61.clientesWS.X43ExpedienteElectronico.TBoolean;
import com.ejie.ab61.clientesWS.X43ExpedienteElectronico.TContact;
import com.ejie.ab61.clientesWS.X43ExpedienteElectronico.TContactList;
import com.ejie.ab61.clientesWS.X43ExpedienteElectronico.TContactType;
import com.ejie.ab61.clientesWS.X43ExpedienteElectronico.TFolder;
import com.ejie.ab61.clientesWS.X43ExpedienteElectronico.TFolderCompleteQuery;
import com.ejie.ab61.clientesWS.X43ExpedienteElectronico.TFolderList;
import com.ejie.ab61.clientesWS.X43ExpedienteElectronico.TFolderQuery;
import com.ejie.ab61.clientesWS.X43ExpedienteElectronico.TFolderSearchType;
import com.ejie.ab61.clientesWS.X43ExpedienteElectronico.TFolderSearchTypeList;
import com.ejie.ab61.clientesWS.X43ExpedienteElectronico.TInterested;
import com.ejie.ab61.clientesWS.X43ExpedienteElectronico.TInterestedList;
import com.ejie.ab61.clientesWS.X43ExpedienteElectronico.TParticipantRRI;
import com.ejie.ab61.clientesWS.X43ExpedienteElectronico.TParticipantRRIList;
import com.ejie.ab61.clientesWS.X43ExpedienteElectronico.TRepresentative;
import com.ejie.ab61.clientesWS.X43ExpedienteElectronico.TStringList;
import com.ejie.ab61.clientesWS.X43Toolkit.Exception_Exception;
import com.ejie.ab61.comun.Constantes;
import com.ejie.ab61.dao.expedientes.ExpedientesDao;
import com.ejie.ab61.model.expedientes.Expedientes;
import com.ejie.ab61.model.terceros.CanalesAviso;
import com.ejie.ab61.model.terceros.DatosTerceros;
import com.ejie.ab61.model.terceros.TiposCanalAviso;
import com.ejie.ab61.model.usuario.Usuario;
import com.ejie.x38.dto.JQGridRequestDto;
import com.ejie.x38.dto.JQGridResponseDto;
import com.ejie.x38.dto.JerarquiaDto;
import com.ejie.x38.dto.TableRowDto;

/**
 * ExpedientesServiceImpl  
 * 
 *  
 */

@Service(value = "expedientesService")
public class ExpedientesServiceImpl implements ExpedientesService {

	@Autowired
	private ExpedientesDao expedientesDao;

	private final static Logger logger = Logger
			.getLogger(com.ejie.ab61.service.expedientes.ExpedientesServiceImpl.class.getName());
	@Autowired
	private X43ExpedienteElectronicoAdaptadorService expedienteElectronicoWS;

	/**
	 * Inserts a single row in the Expedientes table.
	 *
	 * @param expedientes
	 *            Expedientes
	 * @return Expedientes
	 */
	@Transactional(rollbackFor = Throwable.class)
	public Expedientes add(Expedientes expedientes) {
		return this.expedientesDao.add(expedientes);
	}

	/**
	 * Updates a single row in the Expedientes table.
	 *
	 * @param expedientes
	 *            Expedientes
	 * @return Expedientes
	 */
	@Transactional(rollbackFor = Throwable.class)
	public Expedientes update(Expedientes expedientes) {
		return this.expedientesDao.update(expedientes);
	}

	/**
	 * Updates a single row in the Expedientes table.
	 *
	 * @param expedientes
	 *            Expedientes
	 * @return Expedientes
	 */
	@Transactional(rollbackFor = Throwable.class)
	public Expedientes updateFolderNumber(Expedientes expedientes) {
		return this.expedientesDao.updateFolderNumber(expedientes);
	}

	/**
	 * Finds a single row in the Expedientes table.
	 *
	 * @param expedientes
	 *            Expedientes
	 * @return Expedientes
	 */
	public Expedientes find(Expedientes expedientes) {
		return (Expedientes) this.expedientesDao.find(expedientes);
	}

	/**
	 * Finds a single row in the Expedientes table.
	 *
	 * @param expedientes
	 *            Expedientes
	 * @return Expedientes
	 */
	public Expedientes findByFolderId(String folderId) {
		return (Expedientes) this.expedientesDao.findByFolderId(folderId);
	}

	/**
	 * Updates a single row in the Expedientes table.
	 *
	 * @param expedientes
	 *            Expedientes
	 * @return Expedientes
	 */
	@Transactional(rollbackFor = Throwable.class)
	public Expedientes updateFolder(Expedientes expedientes) {
		return this.expedientesDao.updateFolder(expedientes);
	}

	/**
	 * Deletes a single row in the Expedientes table.
	 *
	 * @param expedientes
	 *            Expedientes
	 */
	@Transactional(rollbackFor = Throwable.class)
	public void remove(Expedientes expedientes) {
		this.expedientesDao.remove(expedientes);
	}

	/**
	 * Finds a list of rows in the Expedientes table.
	 *
	 * @param expedientes
	 *            Expedientes
	 * @param jqGridRequestDto
	 *            JQGridRequestDto
	 * @return List<Expedientes>
	 */
	public List<Expedientes> findAll(Expedientes expedientes, JQGridRequestDto jqGridRequestDto) {
		return (List<Expedientes>) this.expedientesDao.findAll(expedientes, jqGridRequestDto);
	}

	/**
	 * Finds rows in the Expedientes table using like.
	 *
	 * @param expedientes
	 *            Expedientes
	 * @param jqGridRequestDto
	 *            JQGridRequestDto
	 * @param startsWith
	 *            Boolean
	 * @return List<Expedientes>
	 */
	public List<Expedientes> findAllLike(Expedientes expedientes, JQGridRequestDto jqGridRequestDto,
			Boolean startsWith) {
		return (List<Expedientes>) this.expedientesDao.findAllLike(expedientes, jqGridRequestDto, startsWith);
	}

	/*
	 * OPERACIONES RUP_TABLE
	 */

	/**
	 * Removes rows from the Expedientes table.
	 *
	 * @param filterExpedientes
	 *            Expedientes
	 * @param jqGridRequestDto
	 *            JQGridRequestDto
	 * @param startsWith
	 *            Boolean
	 */
	public void removeMultiple(Expedientes filterExpedientes, JQGridRequestDto jqGridRequestDto, Boolean startsWith) {
		this.expedientesDao.removeMultiple(filterExpedientes, jqGridRequestDto, startsWith);
	}

	/**
	 * Filter method in the Expedientes table.
	 *
	 * @param filterExpedientes
	 *            Expedientes
	 * @param jqGridRequestDto
	 *            JQGridRequestDto
	 * @param startsWith
	 *            Boolean
	 * @return JQGridResponseDto<Expedientes>
	 */
	public JQGridResponseDto<Expedientes> filter(Expedientes filterExpedientes, JQGridRequestDto jqGridRequestDto,
			Boolean startsWith) {
		List<Expedientes> listaExpedientes = this.expedientesDao.findAllLike(filterExpedientes, jqGridRequestDto,
				false);
		Long recordNum = this.expedientesDao
				.findAllLikeCount(filterExpedientes != null ? filterExpedientes : new Expedientes(), false);
		if (jqGridRequestDto.getMultiselection().getSelectedIds() != null) {
			List<TableRowDto<Expedientes>> reorderSelection = this.expedientesDao.reorderSelection(filterExpedientes,
					jqGridRequestDto, startsWith);
			return new JQGridResponseDto<Expedientes>(jqGridRequestDto, recordNum, listaExpedientes, reorderSelection);
		}
		return new JQGridResponseDto<Expedientes>(jqGridRequestDto, recordNum, listaExpedientes);
	}

	@Override
	public JQGridResponseDto<Expedientes> filterExpedientesRelacionadosUbicacionRelacionExpediente(
			Integer relacionExpediente, Integer idExpediente, JQGridRequestDto jqGridRequestDto) {
		List<Expedientes> listaExpedientesRelacionados = this.expedientesDao
				.findExpedientesRelacionadosUbicacionRelacionExpediente(relacionExpediente, idExpediente,
						jqGridRequestDto);

		Long recordNum = this.expedientesDao
				.findExpedientesRelacionadosUbicacionRelacionExpedienteCount(relacionExpediente, idExpediente);

		return new JQGridResponseDto<Expedientes>(jqGridRequestDto, recordNum, listaExpedientesRelacionados);
	}

	@Override
	public JQGridResponseDto<Expedientes> filterExpedientesARelacionar(Expedientes filterExpedientes,
			Integer idExpediente, JQGridRequestDto jqGridRequestDto, String documentosTitular, boolean startsWith) {
		List<Expedientes> listaExpedientesARelacionar = this.expedientesDao.findExpedientesARelacionar(
				filterExpedientes, idExpediente, jqGridRequestDto, documentosTitular, startsWith);

		Long recordNum = this.expedientesDao.findExpedientesARelacionarCount(
				filterExpedientes != null ? filterExpedientes : new Expedientes(), false, idExpediente,
				documentosTitular);

		return new JQGridResponseDto<Expedientes>(jqGridRequestDto, recordNum, listaExpedientesARelacionar);
	}

	/**
	 * Searches rows in the Expedientes table.
	 *
	 * @param filterExpedientes
	 *            Expedientes
	 * @param searchExpedientes
	 *            Expedientes
	 * @param jqGridRequestDto
	 *            JQGridRequestDto
	 * @param startsWith
	 *            Boolean
	 * @return List<TableRowDto<Expedientes>>
	 */
	public List<TableRowDto<Expedientes>> search(Expedientes filterExpedientes, Expedientes searchExpedientes,
			JQGridRequestDto jqGridRequestDto, Boolean startsWith) {
		return this.expedientesDao.search(filterExpedientes, searchExpedientes, jqGridRequestDto, startsWith);
	}

	/**
	 * Reorder the selection made in Expedientes table.
	 *
	 * @param filterExpedientes
	 *            Expedientes
	 * @param jqGridRequestDto
	 *            JQGridRequestDto
	 * @param startsWith
	 *            Boolean
	 * @return Object
	 */
	public Object reorderSelection(Expedientes filterExpedientes, JQGridRequestDto jqGridRequestDto,
			Boolean startsWith) {
		return this.expedientesDao.reorderSelection(filterExpedientes, jqGridRequestDto, startsWith);
	}

	/*
	 * OPERACIONES RUP_TABLE JERARQUIA
	 */

	/**
	 * Finder method in the hierarchical the Expedientes table.
	 *
	 * @param filterExpedientes
	 *            Expedientes
	 * @param jqGridRequestDto
	 *            JQGridRequestDto
	 * @param startsWith
	 *            Boolean
	 * @return JQGridResponseDto<JerarquiaDto<Expedientes>>
	 */
	public JQGridResponseDto<JerarquiaDto<Expedientes>> jerarquia(Expedientes filterExpedientes,
			JQGridRequestDto jqGridRequestDto, Boolean startsWith) {
		List<JerarquiaDto<Expedientes>> listaExpedientes = this.expedientesDao.findAllLikeJerarquia(filterExpedientes,
				jqGridRequestDto);
		Long recordNum = this.expedientesDao.findAllLikeCountJerarquia(filterExpedientes, jqGridRequestDto);
		return new JQGridResponseDto<JerarquiaDto<Expedientes>>(jqGridRequestDto, recordNum, listaExpedientes);
	}

	/**
	 * Finder method for siblings rows in the hierarchical the Expedientes
	 * table.
	 *
	 * @param filterExpedientes
	 *            Expedientes
	 * @param jqGridRequestDto
	 *            JQGridRequestDto
	 * @return JQGridResponseDto<JerarquiaDto<Expedientes>>
	 */
	public JQGridResponseDto<JerarquiaDto<Expedientes>> jerarquiaChildren(Expedientes filterExpedientes,
			JQGridRequestDto jqGridRequestDto) {
		JQGridResponseDto<JerarquiaDto<Expedientes>> jqGridResponseDto = new JQGridResponseDto<JerarquiaDto<Expedientes>>();
		jqGridResponseDto.addAdditionalParam(JQGridResponseDto.CHILDREN,
				this.expedientesDao.findAllChild(filterExpedientes, jqGridRequestDto));
		return jqGridResponseDto;
	}

	/**
	 * llama al WS searchFolders
	 * 
	 * @param folderId
	 * @return TFolderList
	 * @throws Exception_Exception
	 */
	@Override
	public TFolderList obtenerInfoPlatea(String folderId) throws Exception_Exception {

		logger.info("obtenerInfoPlatea:inicio: folderId: " + folderId);
		String auditUser = Constantes.AUDIT_USER;
		TFolderList resultado = new TFolderList();
		try {
			TFolderQuery query = new TFolderQuery();
			TFolderCompleteQuery tFolderComplete = new TFolderCompleteQuery();

			TStringList folderIdList = new TStringList();

			folderIdList.getItem().add(folderId);

			TFolderSearchType tFolderSearchType = TFolderSearchType.PARAM_ALL;
			TFolderSearchTypeList tFolderSearchTypeList = new TFolderSearchTypeList();
			tFolderSearchTypeList.getParam().add(tFolderSearchType);
			tFolderComplete.setParamList(tFolderSearchTypeList);

			tFolderComplete.setAuditUser(auditUser);
			tFolderComplete.setFolderIDList(folderIdList);
			tFolderComplete.setInterestedMode(TBoolean.TRUE);

			query.setComplete(tFolderComplete);

			resultado = expedienteElectronicoWS.SearchFolders(query, null);

		} catch (Exception e) {
			logger.info("No esta disponible el SearchFolders");
			resultado = null;
		}
		return resultado;
	}

	/**
	 * con el resultado del WS searchFolders obtiene el cif, el nombre y los
	 * canales de aviso
	 * 
	 * @param tercero
	 * @param folderId
	 * @param tipo
	 * @return
	 * @throws Exception_Exception
	 */
	@Override
	public DatosTerceros obtenerInfoPlateaDetalle(DatosTerceros datosTercero, TFolderList resultado, String tipo)
			throws Exception_Exception {

		TFolder folder = resultado.getFolder().get(0);
		TParticipantRRIList lista = folder.getParticipantRRIList();
		List<TParticipantRRI> tParticipantes = lista.getParticipantList();
		List<CanalesAviso> listaCanales = new ArrayList<CanalesAviso>();
		for (int i = 0; i < tParticipantes.size(); i++) {
			TParticipantRRI participant = tParticipantes.get(i);
			TInterestedList Interesados = participant.getInterestedList();
			List<TInterested> listaInteresados = Interesados.getInterested();
			TRepresentative representante = participant.getRepresentative();

			switch (datosTercero.getTipoParticipante()) {
			case 0:
				for (int j = 0; j < listaInteresados.size();) {
					if (listaInteresados.get(j).getInterestedInLaw() == TBoolean.TRUE) {
						TAccount account = listaInteresados.get(j).getAccount();
						buscarCanalesDeAviso(datosTercero, listaCanales, account);
					}
					break;
				}
				break;
			case 1:
				TAccount account = representante.getAccount();
				buscarCanalesDeAviso(datosTercero, listaCanales, account);
				break;
			default:
				break;
			}

		}
		return datosTercero;

	}

	private void buscarCanalesDeAviso(DatosTerceros datosTerceros, List<CanalesAviso> listaCanales, TAccount account) {
		listaCanales.clear();
		TContactList contactList = account.getContactList();
		if (null != contactList) {
			listaCanales.clear();
			List<TContact> contact = contactList.getContact();

			// aqui metemos el tema de canales de aviso
			if (null != account.getContactList() && contactList.getContact().size() > 0) {
				for (int s = 0; s < contact.size(); s++) {
					TContact aviso = contact.get(s);
					TContactType canal = aviso.getChannelType();

					CanalesAviso canalAviso = new CanalesAviso();
					TiposCanalAviso tipoCanalAviso = new TiposCanalAviso();
					if ("SMS".equalsIgnoreCase(canal.value())) {
						tipoCanalAviso.setIdTipoCanalAviso(Constantes.TIPO_CANAL_AVISO_SMS);
						canalAviso.setCanalAviso(aviso.getSms());
					} else if ("EMAIL".equalsIgnoreCase(canal.value())) {
						tipoCanalAviso.setIdTipoCanalAviso(Constantes.TIPO_CANAL_AVISO_EMAIL);
						canalAviso.setCanalAviso(aviso.getEmail());
					}
					logger.info("tipoCanalAviso: getIdTipoCanalAviso(): " + tipoCanalAviso.getIdTipoCanalAviso());
					canalAviso.setTiposCanalAviso(tipoCanalAviso);
					listaCanales.add(canalAviso);
				}

			}
		}
		datosTerceros.setCanalesAvisos(listaCanales);
	}

	/**
	 * Método que actualizar el tiutlo del expediente con el titulo que viene de
	 * Platea (Tramitagune)
	 * 
	 * @param resultado
	 * @param usuario
	 */
	public void actualizarTituloExpediente(TFolderList resultado, Usuario usuario) {
		if (!resultado.getFolder().isEmpty()) {
			// actualizamos en BD
			Expedientes expediente = new Expedientes();
			TFolder expedientPlatea = resultado.getFolder().get(0);
			expediente.setFolderId(expedientPlatea.getFolderID());
			expediente.setTitulo(expedientPlatea.getFolderTitle());
			if (null != usuario.getNombreUsuario() && usuario.getNombreUsuario().length() > 19) {
				expediente.setUsuarioRegistro(usuario.getNombreUsuario().substring(0, 19));
			} else {
				expediente.setUsuarioRegistro(usuario.getNombreUsuario());
			}
			this.expedientesDao.updateFolderTitle(expediente);
		}

	}

	@Transactional
	@Override
	public Expedientes relacionarExpediente(List<Expedientes> listaExpedientesRelacionados,
			Integer idExpedienteARelacionar, Integer idExpedienteOrigenAyudas, Integer relacionExpediente,
			Usuario usuario) {

		Expedientes expediente = new Expedientes();
		expediente.setIdExpediente(idExpedienteARelacionar);
		expediente.setUsuarioUltmodificacion(usuario.getNombreUsuario());

		if (listaExpedientesRelacionados != null) {

			Integer nuevaRelacionExpediente = this.expedientesDao.getNextRelacionExpediente();

			for (Expedientes expedientes : listaExpedientesRelacionados) {
				expedientes.setRelacionExpediente(nuevaRelacionExpediente);
				expedientes.setUsuarioUltmodificacion(usuario.getNombreUsuario());
				if (expedientes.isExpedienteHistorico()) {
					this.expedientesDao.relacionarExpedienteHistorico(expedientes);
				} else {
					this.expedientesDao.relacionarExpediente(expedientes);
				}
			}

			Expedientes expedienteOrigenAyudas = new Expedientes();
			expedienteOrigenAyudas.setIdExpediente(idExpedienteOrigenAyudas);
			expedienteOrigenAyudas.setRelacionExpediente(nuevaRelacionExpediente);
			expedienteOrigenAyudas.setUsuarioUltmodificacion(usuario.getNombreUsuario());
			expediente.setRelacionExpediente(nuevaRelacionExpediente);

			this.expedientesDao.relacionarExpediente(expedienteOrigenAyudas);
			return this.expedientesDao.relacionarExpediente(expediente);

		} else {
			expediente.setRelacionExpediente(relacionExpediente);
			return this.expedientesDao.relacionarExpedienteSinRelacion(expediente, idExpedienteOrigenAyudas);
		}
	}

	@Override
	public Expedientes eliminarRelacion(Expedientes expediente) {
		return this.expedientesDao.eliminarRelacion(expediente);
	}

	@Override
	public Expedientes eliminarRelacionHistorico(Expedientes expediente) {
		return this.expedientesDao.eliminarRelacionHistorico(expediente);
	}

	@Override
	public Expedientes findExpedientes(Expedientes expediente) {
		return this.expedientesDao.findExpedientes(expediente);
	}
}
