package com.ejie.y42b.service;

import java.sql.Blob;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Properties;
import java.util.StringTokenizer;

import javax.activation.DataHandler;
import javax.annotation.Resource;
import javax.mail.MessagingException;
import javax.mail.internet.MimeBodyPart;
import javax.mail.util.ByteArrayDataSource;
import javax.sql.rowset.serial.SerialBlob;
import javax.sql.rowset.serial.SerialRef;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.context.support.ReloadableResourceBundleMessageSource;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import com.ejie.x38.control.exception.ResourceNotFoundException;
import com.ejie.x38.dto.Pagination;
import com.ejie.y42b.constantes.Y42bAgendaConstantes;
import com.ejie.y42b.dao.AdjuntoDao;
import com.ejie.y42b.dao.ComunicacionDao;
import com.ejie.y42b.dao.ComunicacionFileDao;
import com.ejie.y42b.dao.ContactoDao;
import com.ejie.y42b.dao.DestComunicacionDao;
import com.ejie.y42b.dao.EntidadDao;
import com.ejie.y42b.dao.EnvioDao;
import com.ejie.y42b.dao.ItemDao;
import com.ejie.y42b.model.Adjunto;
import com.ejie.y42b.model.Comunicacion;
import com.ejie.y42b.model.ComunicacionFile;
import com.ejie.y42b.model.Contacto;
import com.ejie.y42b.model.DestComunicacion;
import com.ejie.y42b.model.Entidad;
import com.ejie.y42b.model.Envio;
import com.ejie.y42b.model.EnvioSeguimiento;
import com.ejie.y42b.model.Item;
import com.ejie.y42b.model.Localizacion;
import com.ejie.y42b.model.TipoComunicacion;
import com.ejie.y42b.utils.Y42bLocalizacion;
import com.ejie.y42b.utils.Y42bSendMail;
import com.ejie.y42b.utils.Y42bUIDGenerator32;
import com.ejie.y42b.utils.Y42bUtils;
import com.ejie.y42b.utils.beans.MailItemBean;
import com.ejie.y42b.utils.exception.Y42bUDAException;

/**
 * * EnvioServiceImpl  
 * 
 *  
 */

@Service(value = "envioService")
public final class EnvioServiceImpl implements EnvioService {

	private static final Logger logger = LoggerFactory
			.getLogger(EnvioServiceImpl.class);
	@Autowired()
	private EnvioDao envioDao;

	@Autowired()
	private ItemDao itemDao;

	@Autowired()
	private AdjuntoDao adjuntoDao;

	@Autowired()
	private EntidadDao entidadDao;

	@Autowired()
	private ContactoDao contactoDao;

	@Autowired()
	private ComunicacionDao comunicacionDao;

	@Autowired()
	private DestComunicacionDao destComunicacionDao;

	@Autowired()
	private ComunicacionFileDao comunicacionFileDao;

	@Autowired()
	private T17PaisService paisService;

	@Autowired()
	private T17ProvinciaService provinciaService;

	@Autowired()
	private T17MunicipioService municipioService;

	@Autowired()
	private T17LocalidadService localidadService;

	@Autowired()
	private T17CalleService calleService;

	@Resource()
	private ReloadableResourceBundleMessageSource appMessageSource;

	/**
	 * 
	 */
	public EnvioServiceImpl() {

	}

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

		// Elimina resultados anteriores
		this.removePreviousResults(envio);
		// Generar un identificador de envio y crear un nuevo envío.
		envio.setEnvioId(Y42bUIDGenerator32.getInstance().generateId());
		return this.envioDao.add(envio);
	}

	/**
	 * Eliminación de envios sin fecha de operación creados con el mismo
	 * 
	 * @param envio
	 *            Envio
	 */
	private void removePreviousResults(Envio envio) {
		Envio envioAux = new Envio();
		envioAux.setSessionOid(envio.getSessionOid());
		List<Envio> envLst = this.envioDao.findAll(envioAux, null);

		for (Envio e : envLst) {
			if (null == e.getFechaOperacion()) {
				if (null != e.getEnvioId()) {
					// Elimina items
					Item item = new Item();// NOPMD
					item.setEnvio(e);
					List<Item> items = this.itemDao.findAll(item, null);
					for (Item i : items) {
						this.itemDao.remove(i);
						// System.out.println("item: "+i);//NOPMD
					}
					// Elimina adjuntos
					Adjunto adjunto = new Adjunto();// NOPMD
					adjunto.setEnvio(e);
					List<Adjunto> adjuntos = this.adjuntoDao.findAll(adjunto,
							null);
					for (Adjunto j : adjuntos) {
						this.adjuntoDao.remove(j);

					}

				}
				this.envioDao.remove(e);
			}
		}
	}

	/**
	 * Updates a single row in the Envio table.
	 * 
	 * @param envio
	 *            Envio
	 * @return Envio
	 * @exception Exception
	 *                Exception
	 */
	@Transactional(rollbackFor = Throwable.class)
	public Envio update(Envio envio) throws Exception {

		/* Validar datos de negocio */
		this.validarDatos(envio);

		this.envioDao.update(envio);

		return envio;
	}

	/**
	 * Finds a single row in the Envio table.
	 * 
	 * @param envio
	 *            Envio
	 * @return Envio
	 */
	public Envio find(Envio envio) {
		return (Envio) this.envioDao.find(envio);
	}

	/**
	 * Finds a List of rows in the Envio table.
	 * 
	 * @param envio
	 *            Envio
	 * @param pagination
	 *            Pagination
	 * @return List
	 */
	public List<Envio> findAll(Envio envio, Pagination pagination) {
		return (List<Envio>) this.envioDao.findAll(envio, pagination);
	}

	/**
	 * Counts rows in the Envio table.
	 * 
	 * @param envio
	 *            Envio
	 * @return Long
	 */
	public Long findAllCount(Envio envio) {
		return this.envioDao.findAllCount(envio);
	}

	/**
	 * Finds rows in the Envio table using like.
	 * 
	 * @param envio
	 *            Envio
	 * @param pagination
	 *            Pagination
	 * @param startsWith
	 *            Boolean
	 * @return List
	 */
	public List<Envio> findAllLike(Envio envio, Pagination pagination,
			Boolean startsWith) {
		return (List<Envio>) this.envioDao.findAllLike(envio, pagination,
				startsWith);
	}

	/**
	 * Finds rows in the Envio table using like.
	 * 
	 * @param envio
	 *            Envio
	 * @param pagination
	 *            Pagination
	 * @param startsWith
	 *            Boolean
	 * @param fechaDesde
	 *            Date
	 * @param fechaHasta
	 *            Date
	 * @return List
	 */
	public List<EnvioSeguimiento> findAllLikeSeguimiento(Envio envio,
			Pagination pagination, Boolean startsWith, Date fechaDesde,
			Date fechaHasta) {

		List<EnvioSeguimiento> envSegLst = new ArrayList<EnvioSeguimiento>();
		List<Envio> envLst = this.envioDao.findAllLikeSeguimiento(envio,
				pagination, startsWith, fechaDesde, fechaHasta);

		for (Envio e : envLst) {
			// Enviados OK
			Long totalEnviadosOK = this.itemDao.countItemsMailedFromEnvio(
					e.getEnvioId(), true);

			Long total = this.itemDao.countTipoFromEnvio(e.getEnvioId(),
					Y42bAgendaConstantes.TOTAL);
			Long totalContactos = this.itemDao.countTipoFromEnvio(
					e.getEnvioId(), Y42bAgendaConstantes.CONTACTO);
			Long totalEntidades = this.itemDao.countTipoFromEnvio(
					e.getEnvioId(), Y42bAgendaConstantes.ENTIDAD);

			if (null != e.getEnvioId()) {
				// Numero total de envios = nº de seleccionados
				Item i = new Item();// NOPMD
				i.setEnvio(e);
				i.setSeleccionado(Y42bAgendaConstantes.SI);
				Long totalEnvios = this.itemDao.findAllCount(i);
				// Seleccionados con email
				Long seleccionadosConMail = this.itemDao.findAllCountMail(i);

				// Numero de envios no leidos
				i.setFechaMailingRecepcion(null);
				Long totalEnviosNoLeidos = this.itemDao
						.findAllCountSeguimiento(i);
				// Envios leidos
				Long totalEnviosLeidos = totalEnvios - totalEnviosNoLeidos;

				envSegLst.add(new EnvioSeguimiento(e.getEnvioId(), e
						.getMailingAsunto(), e.getFechaOperacion(),
						totalEnviosLeidos, totalEnviosNoLeidos, totalEnvios,
						totalEnviadosOK, seleccionadosConMail, totalContactos,
						totalEntidades, total));// NOPMD
				// 2012/02/29
				// (IDA)
			}
		}

		return envSegLst;

	}

	/**
	 * Counts rows in the Envio table.
	 * 
	 * @param envio
	 *            Envio
	 * @param pagination
	 *            Pagination
	 * @param startsWith
	 *            Boolean
	 * @param fechaDesde
	 *            Date
	 * @param fechaHasta
	 *            Date
	 * @return Long
	 */
	public Long findAllLikeSeguimientoCount(Envio envio, Pagination pagination,
			Boolean startsWith, Date fechaDesde, Date fechaHasta) {
		return this.envioDao.findAllLikeSeguimientoCount(envio, pagination,
				startsWith, fechaDesde, fechaHasta);
	}

	/**
	 * Deletes a single row in the Envio table.
	 * 
	 * @param envio
	 *            Envio
	 * @return
	 */
	@Transactional(rollbackFor = Throwable.class)
	public void remove(Envio envio) {
		Item item = new Item();
		item.setEnvio(new Envio());
		item.getEnvio().setEnvioId(envio.getEnvioId());
		Adjunto adjunto = new Adjunto();
		adjunto.setEnvio(envio);
		// Eliminamos primero los items
		this.itemDao.removeItemsEnvio(item);
		// Eliminamosdespues los adjuntos
		this.adjuntoDao.removeAdjunto(adjunto);
		// Eliminacion del envio
		this.envioDao.remove(envio);

	}

	/**
	 * Deletes multiple rows in the Envio table.
	 * 
	 * @param envioList
	 *            ArrayList
	 * @return
	 */
	@Transactional(rollbackFor = Throwable.class)
	public void removeMultiple(ArrayList<Envio> envioList) {
		for (Envio envioAux : envioList) {
			this.envioDao.remove(envioAux);
		}
	}

	/**
	 * Getter method for EnvioDao
	 * 
	 * @return EnvioDao
	 */
	public EnvioDao getEnvioDao() {
		return this.envioDao;
	}

	/**
	 * Setter method for EnvioDao.
	 * 
	 * @param envioDao
	 *            EnvioDao
	 * @return
	 */
	public void setEnvioDao(EnvioDao envioDao) {
		EnvioServiceImpl.logger.info("Setting Dependency " + envioDao);
		this.envioDao = envioDao;
	}

	/**
	 * Proceso de envios de correos
	 * 
	 * @param idEnvio
	 *            String
	 * @exception Exception
	 *                Exception
	 */
	@Transactional(propagation = Propagation.REQUIRES_NEW, rollbackFor = Throwable.class)
	@Override()
	public void procesoEnviosMail(String idEnvio) throws Exception {
		logger.info("**********procesoEnviosMail INICIO");
		if (idEnvio == null || idEnvio.equals("")) {
			throw new Y42bUDAException();
		} else {
			StringTokenizer strTokenizer = new StringTokenizer(idEnvio, "###");
			String ItemRef = strTokenizer.nextToken();
			idEnvio = strTokenizer.nextToken();

			logger.info("**********idEnvio:" + idEnvio);
			logger.info("**********ItemRef:" + ItemRef);
			String mensaje = "";
			String mensajeConEnlace = "";
			String parteEnlace = "";

			List<Adjunto> mailAdjuntos = null;
			Item mailItem = null;
			Envio mailEnvio = new Envio();
			mailEnvio.setEnvioId(idEnvio);
			mailEnvio = this.envioDao.find(mailEnvio);

			if (mailEnvio != null) {

				Adjunto adjuntoTemp = new Adjunto();
				adjuntoTemp.setEnvio(mailEnvio);
				mailAdjuntos = this.adjuntoDao.findAll(adjuntoTemp, null);
				try {

					Item itemTemp = new Item();
					itemTemp.setItemRef(ItemRef);
					itemTemp.setEnvio(mailEnvio);
					mailItem = this.itemDao.find(itemTemp);

					// Actualiza item
					mailItem.setFechaMailingEnvio(new Date());
					this.itemDao.update(mailItem);

					mensaje = this.procesarTemplate(mailEnvio, mailItem);

					// cuerpo mensaje
					parteEnlace = this.procesarEnlace(mailEnvio, mailItem);
					mensajeConEnlace = mensaje + "<BR><BR>" + parteEnlace;

					if (mailEnvio.getEnvioKontsumonet() != null
							&& mailEnvio.getEnvioKontsumonet().equals(
									Y42bAgendaConstantes.SI)
							&& mailEnvio.getEnvioAContactos() != null
							&& mailEnvio.getEnvioAContactos().equalsIgnoreCase(
									Y42bAgendaConstantes.NO)) {
						// buscar organismo
						Entidad entidad = new Entidad();
						entidad.setEntidadId(ItemRef);
						entidad = this.entidadDao.find(entidad);

						if (entidad != null
								&& entidad.getIskontsumonet() != null
								&& entidad.getIskontsumonet().equals(
										Y42bAgendaConstantes.SI)) {

							EnvioServiceImpl.logger.error("enviaComunicacion");
							this.enviarComunicacion(mailItem, mailEnvio,
									mailAdjuntos, mensaje, entidad);
						} else {
							EnvioServiceImpl.logger.error("enviaMail 1");
							this.enviarMail(mailItem, mailEnvio, mailAdjuntos,
									mensajeConEnlace);
						}
					} else {
						EnvioServiceImpl.logger.error("enviaMail 2");
						this.enviarMail(mailItem, mailEnvio, mailAdjuntos,
								mensajeConEnlace);
					}
				} catch (MessagingException ne) {
					EnvioServiceImpl.logger
							.error("Catch 1 - Error de envio de correo: "
									+ ne.getMessage());
					mailItem.setFechaMailingEnvio(null);
					mailItem.setMailingResponseCode(Y42bAgendaConstantes.RESPONSE_ERROR);
					// Actualiza item
					this.itemDao.update(mailItem);

				} catch (Exception e) {
					EnvioServiceImpl.logger
							.error("Catch 2 - Error de envio de correo: "
									+ e.getMessage());
					mailItem.setFechaMailingEnvio(null);
					mailItem.setMailingResponseCode(Y42bAgendaConstantes.RESPONSE_ERROR);
					// Actualiza item
					this.itemDao.update(mailItem);
				} finally {
					EnvioServiceImpl.logger.error("finally");
					Item itemAux = new Item();
					itemAux.setEnvio(mailEnvio);
					List<Item> lstItems = this.itemDao.findAllMailsPendientes(
							itemAux, null);

					if (lstItems.size() == 0) {
						this.procesarEmailInforme(mailEnvio);
					}
				}
			}
		}
		logger.info("**********procesoEnviosMail FIN");
	}

	// /**
	// * Proceso de envios de correos
	// *
	// * @exception Exception
	// * Exception
	// */
	// @Override()
	// public void procesoEnviosMail() throws Exception {
	//
	// Properties prop = Y42bUtils
	// .loadProperties(Y42bAgendaConstantes.CONFIG_PATH);
	// // Datos de cuenta de correo -Tomar del fichero properties
	// String flag = prop.getProperty(Y42bAgendaConstantes.ACTIVAR_CORREO);
	//
	// Envio mailEnvio = null;
	// Item mailItem = null;
	// List<Adjunto> mailAdjuntos = null;
	// String mensaje = "";
	//
	// try {
	// if ("1".equals(flag)) {
	// EnvioServiceImpl.logger
	// .info("********** procesoEnviosMail:START ");
	// List<Envio> lstEnvios = this.envioDao
	// .findAllPrepararEnviosMail();
	// // this.logger.debug("Count envios: " + lstEnvios.size());
	// if (lstEnvios.size() > 0) {
	//
	// mailEnvio = (Envio) lstEnvios.get(0);
	//
	// Adjunto adjuntoTemp = new Adjunto();
	// adjuntoTemp.setEnvio(mailEnvio);
	// mailAdjuntos = this.adjuntoDao.findAll(adjuntoTemp, null);
	//
	// List<Item> lstItems = mailEnvio.getItems();
	//
	// if (lstItems.size() > 0) {
	// try {
	//
	// Item itemTemp = (Item) lstItems.get(0);
	// itemTemp.setEnvio(mailEnvio);
	// mailItem = this.itemDao.find(itemTemp);
	//
	// // Actualiza item
	// mailItem.setFechaMailingEnvio(new Date());
	// this.itemDao.update(mailItem);
	//
	// mensaje = this
	// .procesarTemplate(mailEnvio, mailItem);
	//
	// MailItemBean mailItemBean = new MailItemBean();
	// mailItemBean.setDestinatario(mailItem.getEmail());
	// mailItemBean
	// .setAsunto(mailEnvio.getMailingAsunto());
	// mailItemBean.setMensaje(mensaje);
	// mailItemBean.setAdjuntos(mailAdjuntos);
	//
	// // Quitar estas dos lineas en pruebas ejie-para
	// // poner un destinatario de ejie válido
	// // mailItemBean.setDestinatario("jcgonzalez@bilbomatica.es");
	// // mailItemBean.setDestinatario("acreditaciones@ejie.es");
	// // mailItemBean.setAsunto("Asunto");
	// EnvioServiceImpl.logger
	// .info("#########Destinatario:########## "
	// + mailItem.getEmail());
	// EnvioServiceImpl.logger
	// .info("#########ItemRef:########## "
	// + mailItem.getItemRef());
	//
	// if (Y42bUtils.normalizarVacio(
	// mailItemBean.getDestinatario()).length() == 0) {
	// mailItem.setFechaMailingEnvio(null);
	// mailItem.setMailingResponseCode("Correo invalido");
	// } else {
	// Y42bSendMail sendMail = new Y42bSendMail();
	// sendMail.sendItem(mailItemBean);
	// // Actualizar fecha de envio del email
	// mailItem.setFechaMailingEnvio(new Date());
	// mailItem.setMailingResponseCode(Y42bAgendaConstantes.RESPONSE_OK);
	// }
	// // Actualiza item
	// this.itemDao.update(mailItem);
	//
	// this.procesarEmailInforme(mailEnvio);
	//
	// } catch (MessagingException ne) {
	// EnvioServiceImpl.logger
	// .error("Error de envio de correo: "
	// + ne.getMessage());
	// mailItem.setFechaMailingEnvio(null);
	// mailItem.setMailingResponseCode(Y42bAgendaConstantes.RESPONSE_ERROR);
	// EnvioServiceImpl.logger.info("" + ne.getMessage());
	// // Actualiza item
	// this.itemDao.update(mailItem);
	// // this.procesarEmailInforme(mailEnvio);
	//
	// } catch (Exception e) {
	// mailItem.setFechaMailingEnvio(null);
	// mailItem.setMailingResponseCode(Y42bAgendaConstantes.RESPONSE_ERROR);
	// // Actualiza item
	// this.itemDao.update(mailItem);
	// // this.procesarEmailInforme(mailEnvio);
	// EnvioServiceImpl.logger.info("" + e.getMessage());
	// // e.printStackTrace();
	//
	// throw new Exception();
	// }
	// }
	// }
	// }
	// } catch (Exception e) {
	// mailItem.setFechaMailingEnvio(null);
	// mailItem.setMailingResponseCode(Y42bAgendaConstantes.RESPONSE_ERROR);
	// EnvioServiceImpl.logger.info("" + e.getMessage());
	// this.procesarEmailInforme(mailEnvio);
	// // e.printStackTrace();
	// throw new Exception();
	//
	// }
	// }

	/**
	 * Proceso de envios de correos
	 * 
	 * @exception Exception
	 *                Exception
	 */
	@Override()
	public void limpiezaEnviosMail() throws Exception {
		List<Envio> lstEnvios = null;
		List<Item> lstItems = null;
		try {
			EnvioServiceImpl.logger
					.info("********** limpiezaEnviosMail:START ");
			// Obtengo los envios que cumplen condiciones
			lstEnvios = this.envioDao.findAllLimpiarEnviosMail();
			EnvioServiceImpl.logger.debug("Count envios: " + lstEnvios.size());
			if (lstEnvios.size() > 0) {
				// por cada envio obtendre los items
				for (Envio e : lstEnvios) {
					if (null != e.getEnvioId()) {
						Item itemTemp = new Item();// NOPMD
						itemTemp.setEnvio(e);
						// Obtengo los item´s por envio
						lstItems = this.itemDao.findLimpiarItems(itemTemp);
						if (lstItems.size() > 0) {
							// Por cada item eliminare los items
							for (Item it : lstItems) {
								// Elimino el item
								this.itemDao.remove(it);
							}
						}
					}
				}
			}
		} catch (Exception e) {
			EnvioServiceImpl.logger.info("" + e.getMessage());
			// e.printStackTrace();
			throw new Exception();

		}
	}

	// *********************************************************************************
	// METODOS PRIVADOS
	// ********************************************************************************

	/**
	 * Procesa el template del campo MailingTemplate
	 * 
	 * @param envio
	 *            Envio
	 * @param item
	 *            Item
	 * @return String
	 */

	private String procesarTemplate(Envio envio, Item item) {

		String template = Y42bUtils.normalizarVacio(envio.getMailingTemplate());
		String tipoOperacion = envio.getTipoOperacion();
		// String tipo = envio.getTipo();

		String primeraLetra = item.getItemRef().substring(0, 1);

		Localizacion localizacion = new Localizacion();

		// Para confirmar la recepción de este correo, por favor, haga clic
		// sobre el siguiente enlace: http://URL de
		// internet?codorg=XX&codenvio=YY
		// template = template.replace("%XX%", item.getItemRef());
		// template = template.replace("%YY%", envio.getEnvioId());

		// Idioma
		Locale locale = LocaleContextHolder.getLocale();
		if (Y42bAgendaConstantes.TIPO_OP_MAILING_DINAMICO.equals(tipoOperacion)) {

			// 1) Obtener Entidad o Contacto en función del tipo de envio
			// envio.getTipo()
			// 2) Replace por tipo de busqueda Entidades y Contactos
			// if (Y42bAgendaConstantes.ENTIDAD.equals(tipo)) {
			if (primeraLetra.equalsIgnoreCase(Y42bAgendaConstantes.ENTIDAD)) {

				Entidad entidad = new Entidad();
				entidad.setEntidadId(item.getItemRef());
				entidad = this.entidadDao.find(entidad);

				if (Y42bAgendaConstantes.EUSKERA.equals(locale.getLanguage())) {
					template = template.replace(
							Y42bAgendaConstantes.CAMPO_NAME,
							Y42bUtils.normalizarVacio(entidad.getNombreEu()));
				} else {
					template = template.replace(
							Y42bAgendaConstantes.CAMPO_NAME,
							Y42bUtils.normalizarVacio(entidad.getNombreEs()));
				}
				template = template.replace(
						Y42bAgendaConstantes.CAMPO_TELEFONO,
						Y42bUtils.normalizarVacio(entidad.getTelefono()));
				template = template.replace(Y42bAgendaConstantes.CAMPO_MAIL,
						Y42bUtils.normalizarVacio(entidad.getEmail()));
				template = template.replace(Y42bAgendaConstantes.CAMPO_FAX,
						Y42bUtils.normalizarVacio(entidad.getFax()));
				template = template.replace(Y42bAgendaConstantes.CAMPO_URL,
						Y42bUtils.normalizarVacio(entidad.getUrl()));
				template = template.replace(Y42bAgendaConstantes.CAMPO_USER,
						Y42bUtils.normalizarVacio(entidad.getUsuario()));
				template = template.replace(
						Y42bAgendaConstantes.CAMPO_PASSWORD,
						Y42bUtils.normalizarVacio(entidad.getPassword()));
				template = template.replace(Y42bAgendaConstantes.CAMPO_CARGO,
						"");
				template = template.replace(Y42bAgendaConstantes.CAMPO_CODORG,
						Y42bUtils.normalizarVacio(entidad.getCodOrg()));

				localizacion.setPaisId(entidad.getNoraPaisId());
				localizacion.setProvinciaId(entidad.getNoraProvinciaId());
				localizacion.setMunicipioId(entidad.getNoraMunicipioId());
				localizacion.setLocalidadId(entidad.getNoraLocalidadId());
				localizacion.setCalleId(entidad.getNoraCalleId());

				// } else if (Y42bAgendaConstantes.CONTACTO.equals(tipo)) {
			} else if (primeraLetra
					.equalsIgnoreCase(Y42bAgendaConstantes.CONTACTO)) {
				Contacto contacto = new Contacto();
				contacto.setContactoId(item.getItemRef());
				contacto = this.contactoDao.find(contacto);

				template = template.replace(Y42bAgendaConstantes.CAMPO_NAME,
						Y42bUtils.normalizarVacio(contacto.getNombre()));
				template = template.replace(
						Y42bAgendaConstantes.CAMPO_TELEFONO,
						Y42bUtils.normalizarVacio(contacto.getTelefono()));
				template = template.replace(Y42bAgendaConstantes.CAMPO_MAIL,
						Y42bUtils.normalizarVacio(contacto.getEmail()));
				template = template.replace(Y42bAgendaConstantes.CAMPO_FAX,
						Y42bUtils.normalizarVacio(contacto.getFax()));
				template = template.replace(Y42bAgendaConstantes.CAMPO_URL,
						Y42bUtils.normalizarVacio(contacto.getUrl()));
				template = template
						.replace(Y42bAgendaConstantes.CAMPO_USER, "");
				template = template.replace(
						Y42bAgendaConstantes.CAMPO_PASSWORD, "");
				template = template.replace(Y42bAgendaConstantes.CAMPO_CARGO,
						Y42bUtils.normalizarVacio(contacto.getCargo()));
				template = template.replace(Y42bAgendaConstantes.CAMPO_CODORG,
						"");

				localizacion.setPaisId(contacto.getNoraPaisId());
				localizacion.setProvinciaId(contacto.getNoraProvinciaId());
				localizacion.setMunicipioId(contacto.getNoraMunicipioId());
				localizacion.setLocalidadId(contacto.getNoraLocalidadId());
				localizacion.setCalleId(contacto.getNoraCalleId());

			}

			Y42bLocalizacion loc = new Y42bLocalizacion(this.paisService,
					this.provinciaService, this.municipioService,
					this.localidadService, this.calleService);
			localizacion = loc.setLocalizacion(localizacion);

			StringBuffer location = new StringBuffer("");
			location.append(Y42bUtils.normalizarVacio(localizacion
					.getCalleNombre()));

			if (Y42bUtils.normalizarVacio(localizacion.getLocalidadNombre())
					.length() > 0) {
				location.append(" , ");
				location.append(Y42bUtils.normalizarVacio(localizacion
						.getLocalidadNombre()));
			}

			if (Y42bUtils.normalizarVacio(localizacion.getMunicipioNombre())
					.length() > 0) {
				location.append(" , ");
				location.append(Y42bUtils.normalizarVacio(localizacion
						.getMunicipioNombre()));
			}

			if (Y42bUtils.normalizarVacio(localizacion.getProvinciaNombre())
					.length() > 0) {
				location.append(" , ");
				location.append(Y42bUtils.normalizarVacio(localizacion
						.getProvinciaNombre()));
			}

			if (Y42bUtils.normalizarVacio(localizacion.getPaisNombre())
					.length() > 0) {
				location.append(" ( ");
				location.append(Y42bUtils.normalizarVacio(localizacion
						.getPaisNombre()));
				location.append(" ) ");
			}

			template = template.replace(Y42bAgendaConstantes.CAMPO_LOCATION,
					location.toString());

			// 3) Si es xmlImportado replaces de %CAMPO1% a %CAMPO10%

			if (Y42bAgendaConstantes.SI.equals(envio.getXmlimportado())) {
				template = template.replace(
						Y42bAgendaConstantes.CAMPO_CAMPO_01,
						Y42bUtils.normalizarVacio(item.getXmlcampo1()));
				template = template.replace(
						Y42bAgendaConstantes.CAMPO_CAMPO_02,
						Y42bUtils.normalizarVacio(item.getXmlcampo2()));
				template = template.replace(
						Y42bAgendaConstantes.CAMPO_CAMPO_03,
						Y42bUtils.normalizarVacio(item.getXmlcampo3()));
				template = template.replace(
						Y42bAgendaConstantes.CAMPO_CAMPO_04,
						Y42bUtils.normalizarVacio(item.getXmlcampo4()));
				template = template.replace(
						Y42bAgendaConstantes.CAMPO_CAMPO_05,
						Y42bUtils.normalizarVacio(item.getXmlcampo5()));
				template = template.replace(
						Y42bAgendaConstantes.CAMPO_CAMPO_06,
						Y42bUtils.normalizarVacio(item.getXmlcampo6()));
				template = template.replace(
						Y42bAgendaConstantes.CAMPO_CAMPO_07,
						Y42bUtils.normalizarVacio(item.getXmlcampo7()));
				template = template.replace(
						Y42bAgendaConstantes.CAMPO_CAMPO_08,
						Y42bUtils.normalizarVacio(item.getXmlcampo8()));
				template = template.replace(
						Y42bAgendaConstantes.CAMPO_CAMPO_09,
						Y42bUtils.normalizarVacio(item.getXmlcampo9()));
				template = template.replace(
						Y42bAgendaConstantes.CAMPO_CAMPO_10,
						Y42bUtils.normalizarVacio(item.getXmlcampo10()));

			}
		}

		return template;
	}

	/**
	 * Procesa el template del campo MailingTemplate
	 * 
	 * @param envio
	 *            Envio
	 * @param item
	 *            Item
	 * @return String
	 */

	private String procesarEnlace(Envio envio, Item item) {

		String acuse = Y42bUtils.normalizarVacio(envio.getAcuse());
		String enlace = "";
		// Para confirmar la recepción de este correo, por favor, haga clic
		// sobre el siguiente enlace: http://URL de
		// internet?codorg=XX&codenvio=YY

		if (acuse.equalsIgnoreCase(Y42bAgendaConstantes.SI)) {

			Properties prop = Y42bUtils
					.loadProperties(Y42bAgendaConstantes.CONFIG_PATH);

			Locale localeEU = new Locale(Y42bAgendaConstantes.EUSKERA);
			Locale localeES = new Locale(Y42bAgendaConstantes.CASTELLANO);

			enlace = "";
			enlace = enlace
					+ this.appMessageSource.getMessage("urlConfigEU", null,
							localeEU);
			enlace = enlace + "&nbsp;<a href=\'"
					+ prop.getProperty("URL_ENVIO_CONFIRMACION") + "\'>";
			enlace = enlace
					+ this.appMessageSource.getMessage("enlaceEU", null,
							localeEU) + "</a>&nbsp;";
			enlace = enlace
					+ this.appMessageSource.getMessage("urlConfig2EU", null,
							localeEU);
			enlace = enlace + "<BR><BR>";
			enlace = enlace
					+ this.appMessageSource.getMessage("urlConfigES", null,
							localeES);
			enlace = enlace + "&nbsp;<a href=\'"
					+ prop.getProperty("URL_ENVIO_CONFIRMACION") + "\'>";
			enlace = enlace
					+ this.appMessageSource.getMessage("enlaceES", null,
							localeES) + "</a>&nbsp;";
			enlace = enlace
					+ this.appMessageSource.getMessage("urlConfig2ES", null,
							localeES);
			enlace = enlace + "<BR><BR>";

			enlace = enlace.replace("%XX%", item.getItemRef());
			enlace = enlace.replace("%YY%", envio.getEnvioId());
		}

		return enlace;
	}

	/**
	 * Enviar mail
	 * 
	 * @param mailItem
	 *            Item
	 * @param mailEnvio
	 *            Envio
	 * @param mailAdjuntos
	 *            List<Adjunto>
	 * @param mensaje
	 *            String
	 * @throws MessagingException
	 */

	private void enviarMail(Item mailItem, Envio mailEnvio,
			List<Adjunto> mailAdjuntos, String mensaje)
			throws MessagingException {

		MailItemBean mailItemBean = new MailItemBean();
		mailItemBean.setDestinatario(mailItem.getEmail());
		mailItemBean.setAsunto(mailEnvio.getMailingAsunto());
		mailItemBean.setMensaje(mensaje);
		mailItemBean.setAdjuntos(mailAdjuntos);

		EnvioServiceImpl.logger.info("#########Destinatario:########## "
				+ mailItem.getEmail());
		EnvioServiceImpl.logger.info("#########ItemRef:########## "
				+ mailItem.getItemRef());

		if (Y42bUtils.normalizarVacio(mailItemBean.getDestinatario()).length() == 0) {
			mailItem.setFechaMailingEnvio(null);
			mailItem.setMailingResponseCode("Correo invalido");
		} else if (mailItem.getSeleccionado().equalsIgnoreCase("S")) {
			Y42bSendMail sendMail = new Y42bSendMail();
			sendMail.sendItem(mailItemBean);
			// Actualizar fecha de envio del email
			mailItem.setFechaMailingEnvio(new Date());
			mailItem.setMailingResponseCode(Y42bAgendaConstantes.RESPONSE_OK);
		}
		// Actualiza item
		this.itemDao.update(mailItem);
	}

	/**
	 * Enviar mail
	 * 
	 * @param mailItem
	 *            Item
	 * @param mailEnvio
	 *            Envio
	 * @param mailAdjuntos
	 *            List<Adjunto>
	 * @param mensaje
	 *            String
	 * @param entidad
	 *            Entidad
	 * @throws Exception
	 */

	private void enviarComunicacion(Item mailItem, Envio mailEnvio,
			List<Adjunto> mailAdjuntos, String mensaje, Entidad entidad)
			throws Exception {
		Comunicacion comunicacion = new Comunicacion();
		comunicacion.setM4cocomu(this.comunicacionDao.getNewPK());

		Properties prop = Y42bUtils
				.loadProperties(Y42bAgendaConstantes.CONFIG_PATH);

		Entidad organismoComunicacion = new Entidad();
		organismoComunicacion.setCodOrg(prop
				.getProperty("envioComunicacion_codigoOrganismoOrigen"));

		TipoComunicacion tipoComunicacion = new TipoComunicacion(
				Y42bAgendaConstantes.TIPO_COMUNICACION_NO_REPLY, null, null,
				null, null, null, null, null);

		comunicacion.setOrganismo(organismoComunicacion);
		comunicacion.setTipoComunicacion(tipoComunicacion);
		comunicacion.setM4tesubject(mailEnvio.getMailingAsunto());
		comunicacion.setM4tecomu(mensaje);
		comunicacion.setM4noremi(mailEnvio.getRemitenteEnvio());

		// Evita problemas con las fechas desde hasta
		Locale locale = LocaleContextHolder.getLocale();

		if (!(Y42bAgendaConstantes.EUSKERA.equals(locale.getLanguage()))
				&& !(Y42bAgendaConstantes.CASTELLANO.equals(locale
						.getLanguage()))) {
			locale = new Locale(Y42bAgendaConstantes.CASTELLANO);
		}

		Date today = new Date();

		EnvioServiceImpl.logger
				.error("EnvioServiceImpl - enviarComunicacion, codOrgOrigenComunicacion:"
						+ prop.getProperty("envioComunicacion_codigoOrganismoOrigen")
						+ " today:" + today + " locale:" + locale);

		Date todayWithZeroTime = Y42bUtils.parseDate(today, locale);

		comunicacion.setM4feenv(todayWithZeroTime);
		comunicacion.setM4fecad(todayWithZeroTime);

		comunicacion.setM4nudest(new Long(1));
		comunicacion.setM4nufiladj(new Long(0));
		comunicacion.setM4incomact(0);
		comunicacion.setM4incombl(0);

		comunicacion.setM4envioid(mailEnvio.getEnvioId());

		this.comunicacionDao.add(comunicacion);

		Comunicacion com = new Comunicacion();
		com.setM4cocomu(comunicacion.getM4cocomu());

		ComunicacionFile comfile = new ComunicacionFile();

		if (mailAdjuntos != null) {

			for (Adjunto adjunto : mailAdjuntos) {
				if (adjunto.getAdjunto() != null) {

					comfile.setM3cofile(this.comunicacionFileDao.getNewPK());
					Blob blob = new SerialBlob(adjunto.getAdjunto().getBytes(1,
							(int) adjunto.getAdjunto().length()));
					comfile.setM3datafile(blob);
					comfile.setM3contenttypefile(adjunto.getContentType());
					comfile.setM3nofile(adjunto.getNombre());
					comfile.setM3sizefile((int) adjunto.getAdjunto().length());
					comfile.setM3tedesfile("");
					comfile.setComunicacion(com);

					ComunicacionFile comFileAux = this.comunicacionFileDao
							.add(comfile);

				}
			}
		}

		DestComunicacion destcomunicacion = new DestComunicacion();

		Entidad organismoDestComunicacion = new Entidad();
		organismoDestComunicacion.setCodOrg(entidad.getCodOrg());

		destcomunicacion.setOrganismo(organismoDestComunicacion);
		destcomunicacion.setComunicacion(comunicacion);

		this.destComunicacionDao.add(destcomunicacion);

		mailItem.setFechaMailingEnvio(new Date());
		mailItem.setMailingResponseCode(Y42bAgendaConstantes.RESPONSE_OK);

		this.itemDao.update(mailItem);

	}

	/**
	 * Validar datos de pantalla.
	 * 
	 * @param envio
	 *            Envio
	 * @throws Exception
	 *             Exception
	 */
	private void validarDatos(Envio envio) throws Exception {
		Locale locale = LocaleContextHolder.getLocale();

		// Normalizar valores
		String mailingAsunto = Y42bUtils.normalizarCero(envio
				.getMailingAsunto());

		StringBuffer errNegocio = new StringBuffer();

		if ("0".equals(mailingAsunto)) {
			// errNegocio.append("<li>");
			errNegocio.append(this.appMessageSource.getMessage(
					"required.mailingAsunto", null, locale));
			// errNegocio.append("</li>");
		}

		if (errNegocio.length() == 0) {
			EnvioServiceImpl.logger.debug("Entidad valida.");
		} else {
			EnvioServiceImpl.logger
					.debug("Se presentaron errores al validar la entidad.");

			throw new ResourceNotFoundException(errNegocio.toString());

		}

		// throw new Exception("esto es una prueba");

	}

	/**
	 * Validar datos de pantalla.
	 * 
	 * @param mailEnvio
	 *            Envio
	 * @param correctos
	 *            int
	 * @param erroneos
	 *            int
	 * @param direccionesErroneas
	 *            String
	 * @return MailItemBean
	 */
	private MailItemBean generarEmailInforme(Envio mailEnvio, long correctos,
			long erroneos, String direccionesErroneas) {

		MailItemBean mailItemBean = new MailItemBean();

		StringBuffer strBMensaje = new StringBuffer(
				Y42bAgendaConstantes.BUFFER_300);

		String totalesES = appMessageSource.getMessage("envio.totales", null,
				new Locale(Y42bAgendaConstantes.CASTELLANO));
		String correctosES = appMessageSource.getMessage("envio.correctos",
				null, new Locale(Y42bAgendaConstantes.CASTELLANO));
		String erroneosES = appMessageSource.getMessage("envio.erroneos", null,
				new Locale(Y42bAgendaConstantes.CASTELLANO));
		String direccionesErroneasES = appMessageSource.getMessage(
				"envio.direccioneserroneas", null, new Locale(
						Y42bAgendaConstantes.CASTELLANO));
		String enviadoAsuntoES = appMessageSource.getMessage(
				"envio.enviadoAsunto", null, new Locale(
						Y42bAgendaConstantes.CASTELLANO));
		String enviadoCuerpoES = appMessageSource.getMessage(
				"envio.enviadoCuerpo", null, new Locale(
						Y42bAgendaConstantes.CASTELLANO));
		String asuntoInforme = appMessageSource.getMessage(
				"envio.asuntoInforme", null, new Locale(
						Y42bAgendaConstantes.CASTELLANO))
				+ " / "
				+ appMessageSource.getMessage("envio.asuntoInforme", null,
						new Locale(Y42bAgendaConstantes.EUSKERA));
		String totalesEU = appMessageSource.getMessage("envio.totales", null,
				new Locale(Y42bAgendaConstantes.EUSKERA));
		String correctosEU = appMessageSource.getMessage("envio.correctos",
				null, new Locale(Y42bAgendaConstantes.EUSKERA));
		String erroneosEU = appMessageSource.getMessage("envio.erroneos", null,
				new Locale(Y42bAgendaConstantes.EUSKERA));
		String direccionesErroneasEU = appMessageSource.getMessage(
				"envio.direccioneserroneas", null, new Locale(
						Y42bAgendaConstantes.EUSKERA));
		String enviadoAsuntoEU = appMessageSource.getMessage(
				"envio.enviadoAsunto", null, new Locale(
						Y42bAgendaConstantes.EUSKERA));
		String enviadoCuerpoEU = appMessageSource.getMessage(
				"envio.enviadoCuerpo", null, new Locale(
						Y42bAgendaConstantes.EUSKERA));

		// ES
		strBMensaje.append("<p>").append("<b>").append(totalesES).append(": ")
				.append("</b>").append((correctos + erroneos)).append("</p>");
		strBMensaje.append("<p>").append("<b>").append(correctosES)
				.append(": ").append("</b>").append(correctos).append("</p>");
		strBMensaje.append("<p>").append("<b>").append(erroneosES).append(": ")
				.append("</b>").append(erroneos).append("</p>");
		if (erroneos > 0) {
			strBMensaje.append("<p>").append("<b>")
					.append(direccionesErroneasES).append(": ").append("</b>")
					.append("<p>").append(direccionesErroneas).append("</p>")
					.append("</p>");
		}
		strBMensaje.append("<p>").append("<b>").append(enviadoAsuntoES)
				.append(": ").append("</b>").append("<p>")
				.append(mailEnvio.getMailingAsunto()).append("</p>")
				.append("</p>");
		strBMensaje
				.append("<p>")
				.append("<b>")
				.append(enviadoCuerpoES)
				.append(": ")
				.append("</b>")
				.append("<p>")
				.append(mailEnvio.getMailingTemplate() != null ? mailEnvio
						.getMailingTemplate() : "").append("</p>")
				.append("</p>");

		strBMensaje.append("<br>").append("<br>");
		// EU
		strBMensaje.append("<p>").append("<b>").append(totalesEU).append(": ")
				.append("</b>").append((correctos + erroneos)).append("</p>");
		strBMensaje.append("<p>").append("<b>").append(correctosEU)
				.append(": ").append("</b>").append(correctos).append("</p>");
		strBMensaje.append("<p>").append("<b>").append(erroneosEU).append(": ")
				.append("</b>").append(erroneos).append("</p>");
		if (erroneos > 0) {
			strBMensaje.append("<p>").append("<b>")
					.append(direccionesErroneasEU).append(": ").append("</b>")
					.append("<p>").append(direccionesErroneas).append("</p>")
					.append("</p>");
		}
		strBMensaje.append("<p>").append("<b>").append(enviadoAsuntoEU)
				.append(": ").append("</b>").append("<p>")
				.append(mailEnvio.getMailingAsunto()).append("</p>")
				.append("</p>");
		strBMensaje
				.append("<p>")
				.append("<b>")
				.append(enviadoCuerpoEU)
				.append(": ")
				.append("</b>")
				.append("<p>")
				.append(mailEnvio.getMailingTemplate() != null ? mailEnvio
						.getMailingTemplate() : "").append("</p>")
				.append("</p>");

		mailItemBean.setDestinatario(mailEnvio.getDestinatarioInforme());
		mailItemBean.setAsunto(asuntoInforme);
		mailItemBean.setMensaje(strBMensaje.toString());

		// mailItemBean.setAdjuntos(mailAdjuntos);

		return mailItemBean;
	}

	/**
	 * Envia correo informe tras procesar el ultimo item del envio de mails
	 * 
	 * @param mailEnvio
	 *            Envio
	 * @throws Exception
	 *             Exception
	 */
	private void procesarEmailInforme(Envio mailEnvio) throws Exception {
		long contCorrectos = 0;
		long contErroneos = 0;
		StringBuffer direccionesErroneas = new StringBuffer();

		// consultar el envio y ver si hay pendientes
		// =contar items con email y sin estado OK o ERROR
		long numItemsNotMailed = this.itemDao
				.countItemsNotMailedYetFromEnvio(mailEnvio.getEnvioId());
		if (numItemsNotMailed == 0) {
			// contador correctos
			contCorrectos = this.itemDao.countItemsMailedFromEnvio(
					mailEnvio.getEnvioId(), true);
			// contador erroneos
			contErroneos = this.itemDao.countItemsMailedFromEnvio(
					mailEnvio.getEnvioId(), false);
			// direcciones erroneas
			Envio miEnvio = new Envio();
			miEnvio.setEnvioId(mailEnvio.getEnvioId());
			Item itemNoEnviado = new Item();
			itemNoEnviado.setEnvio(miEnvio);

			List<Item> itemsConEmailFallado = this.itemDao.findAllLike(
					itemNoEnviado, null, false);

			Iterator<Item> it = itemsConEmailFallado.iterator();
			while (it.hasNext()) {
				Item itemConMail = it.next();

				if (itemConMail.getEmail() != null
						&& itemConMail.getSeleccionado().equalsIgnoreCase("S")
						&& itemConMail.getMailingResponseCode() != null
						&& itemConMail.getMailingResponseCode()
								.equalsIgnoreCase("ERROR")) {
					direccionesErroneas.append(",");
					direccionesErroneas.append(itemConMail.getEmail());
				}
			}

			try {
				// si no hay pendientes se envia mail resumen
				MailItemBean mailItemBeanInforme = this.generarEmailInforme(
						mailEnvio, contCorrectos, contErroneos,
						direccionesErroneas.toString());
				Y42bSendMail sendMailInforme = new Y42bSendMail();
				sendMailInforme.sendItem(mailItemBeanInforme);
			} catch (Exception e) {
				EnvioServiceImpl.logger.info("" + e.getMessage());
				// e.printStackTrace();
				throw new Exception();
			}
		}
	}

	/**
	 * Counts rows in the Envio table.
	 * 
	 * @param envio
	 *            Envio
	 * @return Long
	 */
	public Long findAllCountKontsumonet(String envioId) {
		return this.envioDao.findAllCountKontsumonet(envioId);
	}

}
