package com.ejie.ab04b.service;

import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Properties;

import org.codehaus.jackson.JsonGenerationException;
import org.codehaus.jackson.map.JsonMappingException;
import org.codehaus.jackson.map.ObjectMapper;
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.Transactional;

import com.ejie.ab04b.constantes.Constantes;
import com.ejie.ab04b.dao.VlistestprevDao;
import com.ejie.ab04b.exception.AB04BException;
import com.ejie.ab04b.model.Vlistestprev;
import com.ejie.ab04b.util.PropertiesUtil;
import com.ejie.ab04b.util.Utilities;
import com.ejie.ab04b.webservice.client.documentowebservice.AlineacionCol;
import com.ejie.ab04b.webservice.client.documentowebservice.AlineacionZona;
import com.ejie.ab04b.webservice.client.documentowebservice.DefinicionCab;
import com.ejie.ab04b.webservice.client.documentowebservice.DefinicionCol;
import com.ejie.ab04b.webservice.client.documentowebservice.DefinicionPag;
import com.ejie.ab04b.webservice.client.documentowebservice.DefinicionPie;
import com.ejie.ab04b.webservice.client.documentowebservice.DocumentoWebServiceImpl;
import com.ejie.ab04b.webservice.client.documentowebservice.Elemento;
import com.ejie.ab04b.webservice.client.documentowebservice.Grupo;
import com.ejie.ab04b.webservice.client.documentowebservice.Modo;
import com.ejie.ab04b.webservice.client.documentowebservice.Orientacion;
import com.ejie.ab04b.webservice.client.documentowebservice.Tamano;
import com.ejie.ab04b.webservice.client.documentowebservice.Tipo;
import com.ejie.ab04b.webservice.client.documentowebservice.Zona;
import com.ejie.x38.dto.JQGridRequestDto;
import com.ejie.x38.dto.JQGridResponseDto;
import com.ejie.x38.dto.TableRowDto;

/**
 * VlistestprevServiceImpl generated by UDA, 19-sep-2017 13:57:16.
 * 
 * @author UDA
 */

@Service(value = "vlistestprevService")
public class VlistestprevServiceImpl implements VlistestprevService {

	@Autowired()
	private DocumentoWebServiceImpl documentoWebServiceImpl;

	@Autowired()
	private ReloadableResourceBundleMessageSource appMessageSource;

	@Autowired()
	private Properties appConfiguration;

	@Autowired()
	private VlistestprevDao vlistestprevDao;

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

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

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

	/**
	 * Finds a single row in the Vlistestprev table.
	 * 
	 * vlistestprev Vlistestprev Vlistestprev
	 *
	 * @param vlistestprev
	 *            the vlistestprev
	 * @return the vlistestprev
	 */
	public Vlistestprev find(Vlistestprev vlistestprev) {
		return (Vlistestprev) this.vlistestprevDao.find(vlistestprev);
	}

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

	/**
	 * Finds a list of rows in the Vlistestprev table.
	 * 
	 * vlistestprev Vlistestprev jqGridRequestDto JQGridRequestDto List
	 * <Vlistestprev>
	 *
	 * @param vlistestprev
	 *            the vlistestprev
	 * @param jqGridRequestDto
	 *            the jq grid request dto
	 * @return the list
	 */
	public List<Vlistestprev> findAll(Vlistestprev vlistestprev,
			JQGridRequestDto jqGridRequestDto) {
		return (List<Vlistestprev>) this.vlistestprevDao.findAll(vlistestprev,
				jqGridRequestDto);
	}

	/**
	 * Finds rows in the Vlistestprev table using like.
	 * 
	 * vlistestprev Vlistestprev jqGridRequestDto JQGridRequestDto startsWith
	 * Boolean List<Vlistestprev>
	 *
	 * @param vlistestprev
	 *            the vlistestprev
	 * @param jqGridRequestDto
	 *            the jq grid request dto
	 * @param startsWith
	 *            the starts with
	 * @return the list
	 */
	public List<Vlistestprev> findAllLike(Vlistestprev vlistestprev,
			JQGridRequestDto jqGridRequestDto, Boolean startsWith) {
		return (List<Vlistestprev>) this.vlistestprevDao
				.findAllLike(vlistestprev, jqGridRequestDto, startsWith);
	}

	/*
	 * OPERACIONES RUP_TABLE
	 */

	/**
	 * Removes rows from the Vlistestprev table.
	 * 
	 * filterVlistestprev Vlistestprev jqGridRequestDto JQGridRequestDto
	 * startsWith Boolean
	 *
	 * @param filterVlistestprev
	 *            the filter vlistestprev
	 * @param jqGridRequestDto
	 *            the jq grid request dto
	 * @param startsWith
	 *            the starts with
	 */
	public void removeMultiple(Vlistestprev filterVlistestprev,
			JQGridRequestDto jqGridRequestDto, Boolean startsWith) {
		this.vlistestprevDao.removeMultiple(filterVlistestprev,
				jqGridRequestDto, startsWith);
	}

	/**
	 * Filter method in the Vlistestprev table.
	 * 
	 * filterVlistestprev Vlistestprev jqGridRequestDto JQGridRequestDto
	 * startsWith Boolean JQGridResponseDto<Vlistestprev>
	 *
	 * @param filterVlistestprev
	 *            the filter vlistestprev
	 * @param jqGridRequestDto
	 *            the jq grid request dto
	 * @param startsWith
	 *            the starts with
	 * @return the JQ grid response dto
	 */
	public JQGridResponseDto<Vlistestprev> filter(
			Vlistestprev filterVlistestprev, JQGridRequestDto jqGridRequestDto,
			Boolean startsWith) {
		List<Vlistestprev> listaVlistestprev = this.vlistestprevDao
				.findAllLike(filterVlistestprev, jqGridRequestDto, false);
		Long recordNum = this.vlistestprevDao
				.findAllLikeCount(filterVlistestprev != null
						? filterVlistestprev : new Vlistestprev(), false);
		if (jqGridRequestDto.getMultiselection().getSelectedIds() != null) {
			List<TableRowDto<Vlistestprev>> reorderSelection = this.vlistestprevDao
					.reorderSelection(filterVlistestprev, jqGridRequestDto,
							startsWith);
			return new JQGridResponseDto<Vlistestprev>(jqGridRequestDto,
					recordNum, listaVlistestprev, reorderSelection);
		}
		return new JQGridResponseDto<Vlistestprev>(jqGridRequestDto, recordNum,
				listaVlistestprev);
	}

	/**
	 * Searches rows in the Vlistestprev table.
	 * 
	 * filterVlistestprev Vlistestprev searchVlistestprev Vlistestprev
	 * jqGridRequestDto JQGridRequestDto startsWith Boolean List<TableRowDto
	 * <Vlistestprev>>
	 *
	 * @param filterVlistestprev
	 *            the filter vlistestprev
	 * @param searchVlistestprev
	 *            the search vlistestprev
	 * @param jqGridRequestDto
	 *            the jq grid request dto
	 * @param startsWith
	 *            the starts with
	 * @return the list
	 */
	public List<TableRowDto<Vlistestprev>> search(
			Vlistestprev filterVlistestprev, Vlistestprev searchVlistestprev,
			JQGridRequestDto jqGridRequestDto, Boolean startsWith) {
		return this.vlistestprevDao.search(filterVlistestprev,
				searchVlistestprev, jqGridRequestDto, startsWith);
	}

	/**
	 * Reorder the selection made in Vlistestprev table.
	 * 
	 * filterVlistestprev Vlistestprev jqGridRequestDto JQGridRequestDto
	 * startsWith Boolean Object
	 *
	 * @param filterVlistestprev
	 *            the filter vlistestprev
	 * @param jqGridRequestDto
	 *            the jq grid request dto
	 * @param startsWith
	 *            the starts with
	 * @return the object
	 */
	public Object reorderSelection(Vlistestprev filterVlistestprev,
			JQGridRequestDto jqGridRequestDto, Boolean startsWith) {
		return this.vlistestprevDao.reorderSelection(filterVlistestprev,
				jqGridRequestDto, startsWith);
	}

	/**
	 * Devuelve la ruta del pdf generado.
	 * 
	 * filtro Vlistestprev jqGridRequestDto JQGridRequestDto String
	 *
	 * @param filtro
	 *            the filtro
	 * @param jqGridRequestDto
	 *            the jq grid request dto
	 * @return the string
	 * @throws AB04BException
	 *             the AB 04 B exception
	 */
	public String filterVlistestprevPDF(Vlistestprev filtro,
			JQGridRequestDto jqGridRequestDto) throws AB04BException {
		try {
			String informe = "";

			HashMap<String, String> hmDatosFila = new HashMap<String, String>();
			List<HashMap<String, String>> hmDatos = new ArrayList<HashMap<String, String>>();

			List<Vlistestprev> listadoEstadistica = this.vlistestprevDao
					.findAllLike(filtro, jqGridRequestDto, false);

			if (!listadoEstadistica.isEmpty()) {

				for (int i = 0; i < listadoEstadistica.size(); i++) {

					hmDatosFila = this.inicializarHmDatosFila();

					hmDatosFila.put("territorio",
							listadoEstadistica.get(i).getTerritorioDesc());
					hmDatosFila.put("anio",
							listadoEstadistica.get(i).getAnio());
					hmDatosFila.put("mes", listadoEstadistica.get(i).getMes());
					hmDatosFila.put("total", Long
							.toString(listadoEstadistica.get(i).getTotal()));
					hmDatosFila.put("tipodocpre",
							listadoEstadistica.get(i).getTipodocumento());
					hmDatosFila.put("tipoorgpre",
							listadoEstadistica.get(i).getModalies());
					hmDatosFila.put("auditoria",
							listadoEstadistica.get(i).getAuditoria());

					hmDatos.add(hmDatosFila);
				}
			}

			DefinicionCab defCab;
			String titulo = "";
			DefinicionPie defPie = null;

			defCab = this.setDefinicionCab(filtro.getTerritorio());
			Locale locale = LocaleContextHolder.getLocale();

			defPie = this.setDefinicionPie();

			titulo = this.appMessageSource
					.getMessage("titulo.estadisticaDocPrev", null, locale)
					.toUpperCase();

			String descProvincia;

			if (filtro.getTerritorio() != null) {
				descProvincia = Utilities.getInstance()
						.strTerritorio(filtro.getTerritorio());
			} else {
				descProvincia = this.appMessageSource.getMessage("label.todos",
						null, locale);
			}
			filtro.setTerritorioDesc(descProvincia);

			String tituloConFiltro = this.obtenerTituloFiltro(titulo, filtro,
					null);

			DefinicionPag defPag = this.setDefinicionPag(tituloConFiltro);

			String modo;
			modo = Modo.PDF.toString();

			// Grupos
			List<Grupo> listaGrupos = new ArrayList<Grupo>();
			listaGrupos.add(new Grupo(
					this.obtenerListaColumnasSinInfoOsalanPDF(), "GRUPO1"));

			String jsonString = this.convertirJson(hmDatos);
			String jsonStringGr = this.convertirJsonGr(listaGrupos);

			String extension = ".pdf";

			String rutaPif = this.appConfiguration
					.getProperty(PropertiesUtil.PIF_RUTA_APP)
					.concat(titulo.replace("(", "-").replace(")", "-"))
					.concat(extension);
			informe = this.documentoWebServiceImpl.generarInformePif(
					jsonStringGr, defPag, jsonString, defCab, defPie, modo,
					rutaPif);

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

	/**
	 * MÃ©todo para crear la definiciÃ³n de la cabecera (Zona zona1, Zona zona2,
	 * Zona zona3, Integer tam), las zonas (String tipo, Elemento elemento,
	 * String alineacion) y los elementos (String text, byte[] img).
	 * 
	 * territorio String DefinicionCab
	 *
	 * @param territorio
	 *            the territorio
	 * @return the definicion cab
	 * @throws AB04BException
	 *             Exception
	 */
	private DefinicionCab setDefinicionCab(String territorio)
			throws AB04BException {
		// try {
		Locale locale = LocaleContextHolder.getLocale();

		// String codDelegacion = K72BXLNetUtils.dameDelegacion();
		// String file =
		// this.appConfiguration.getProperty("ruta.imagen".concat(codDelegacion));
		String file = "";
		if (territorio != null) {
			file = this.appConfiguration
					.getProperty("ruta.imagen".concat(territorio));
		} else {
			file = this.appConfiguration
					.getProperty("ruta.imagen".concat(Constantes.TH_TODOS));
		}

		ByteArrayOutputStream ous = null;
		// InputStream ios = null;
		FileInputStream ios = null;
		try {
			byte[] buffer = new byte[Constantes.STRING_BUILDER_INIT];
			ous = new ByteArrayOutputStream();

			ios = new FileInputStream(file);

			int read = 0;
			try {
				while ((read = ios.read(buffer)) != -1) {

					ous.write(buffer, 0, read);
				}
			} catch (IOException e) {
				throw new AB04BException(e, e.getMessage());
			} finally {
				try {
					if (ios != null) {
						ios.close();
					}
				} catch (IOException e) {
					VlistestprevServiceImpl.logger
							.error("ERROR en setDefinicionCab", e);
				}
			}

			byte[] img = ous.toByteArray();

			Date now = new Date();

			String s1 = Utilities.getInstance().formatearDateIdioma(now);

			// DefinicionCab
			return new DefinicionCab(
					new Zona(Tipo.TEXTO,
							new Elemento(
									this.appMessageSource
											.getMessage("titulo.aplicacion",
													null, locale)
											.toUpperCase(),
									null),
							AlineacionZona.CENTRO),
					new Zona(Tipo.IMAGEN, new Elemento(null, img),
							AlineacionZona.CENTRO),
					new Zona(
							Tipo.TEXTO, new Elemento(
									this.appMessageSource
											.getMessage("titulo.fecha", null,
													locale)
											.toUpperCase().concat(" ")
											.concat(s1),
									null),
							AlineacionZona.CENTRO),
					Constantes.CIENTO_TREINTA);
		} catch (IOException e) {
			throw new AB04BException(e, e.getMessage());
		} finally {
			try {
				if (ous != null) {
					ous.close();
				}

				if (ios != null) {
					ios.close();
				}
			} catch (IOException e) {
				VlistestprevServiceImpl.logger
						.error("ERROR en setDefinicionCab", e);
			}
		}
		// } catch (Exception e) {
		// throw new AB04BException(e, e.getMessage());
		// }
	}

	/**
	 * Obtener lista columnas sin info osalan PDF.
	 * 
	 * List<DefinicionCol>
	 *
	 * @return the list
	 */
	private List<DefinicionCol> obtenerListaColumnasSinInfoOsalanPDF() {

		Locale locale = LocaleContextHolder.getLocale();
		List<DefinicionCol> listaColumnas = new ArrayList<DefinicionCol>();
		listaColumnas.add(new DefinicionCol(
				this.appMessageSource.getMessage("titulo.territorio", null,
						locale),
				"territorio", Constantes.DOS, AlineacionCol.IZQUIERDA,
				Constantes.NUEVE, Constantes.DOS, false, true));

		listaColumnas.add(new DefinicionCol(
				this.appMessageSource.getMessage("titulo.anyo", null, locale),
				"anio", Constantes.DOS, AlineacionCol.IZQUIERDA,
				Constantes.NUEVE, Constantes.DOS, false, true));

		listaColumnas.add(new DefinicionCol(
				this.appMessageSource.getMessage("titulo.mes", null, locale),
				"mes", Constantes.DOS, AlineacionCol.IZQUIERDA,
				Constantes.NUEVE, Constantes.DOS, false, true));

		listaColumnas.add(new DefinicionCol(
				this.appMessageSource.getMessage("titulo.total", null, locale),
				"total", Constantes.TRES, AlineacionCol.IZQUIERDA,
				Constantes.NUEVE, Constantes.DOS, false, true));

		listaColumnas.add(new DefinicionCol(
				this.appMessageSource.getMessage("titulo.tipodocpre", null,
						locale),
				"tipodocpre", Constantes.DOS, AlineacionCol.IZQUIERDA,
				Constantes.NUEVE, Constantes.DOS, false, true));

		listaColumnas.add(new DefinicionCol(
				this.appMessageSource.getMessage("titulo.tipoorgpre", null,
						locale),
				"tipoorgpre", Constantes.DOS, AlineacionCol.IZQUIERDA,
				Constantes.NUEVE, Constantes.DOS, false, true));

		listaColumnas.add(new DefinicionCol(
				this.appMessageSource.getMessage("titulo.auditoria", null,
						locale),
				"auditoria", Constantes.TRES, AlineacionCol.IZQUIERDA,
				Constantes.NUEVE, Constantes.DOS, false, true));

		return listaColumnas;
	}

	/**
	 * Obtener titulo filtro.
	 * 
	 * titulo String filtro ComunicacionApertura fechaObtencion Date String
	 *
	 * @param titulo
	 *            the titulo
	 * @param filtro
	 *            the filtro
	 * @param fechaObtencion
	 *            the fecha obtencion
	 * @return the string
	 */
	private String obtenerTituloFiltro(String titulo, Vlistestprev filtro,
			Date fechaObtencion) {

		Locale locale = LocaleContextHolder.getLocale();
		StringBuilder tituloConFiltro = new StringBuilder(
				Constantes.TAMANYO_3000);
		String tab = "   ";

		tituloConFiltro.append(titulo);
		tituloConFiltro.append("\n");
		if (filtro.getTerritorioDesc() != null) {
			tituloConFiltro.append(tab);
			tituloConFiltro.append(this.appMessageSource
					.getMessage("titulo.territorio", null, locale));
			tituloConFiltro.append(":" + tab);
			tituloConFiltro.append(filtro.getTerritorioDesc());
		}
		if (filtro.getAnio() != null) {
			tituloConFiltro.append(tab);
			tituloConFiltro.append(this.appMessageSource
					.getMessage("titulo.anyo", null, locale));
			tituloConFiltro.append(":" + tab);
			tituloConFiltro.append(filtro.getAnio());
		}
		if (filtro.getMes() != null) {
			tituloConFiltro.append(tab);
			tituloConFiltro.append(this.appMessageSource
					.getMessage("titulo.mes", null, locale));
			tituloConFiltro.append(":" + tab);
			tituloConFiltro.append(filtro.getMes());
		}
		if (filtro.getTotal() > 0) {
			tituloConFiltro.append(tab);
			tituloConFiltro.append(this.appMessageSource
					.getMessage("titulo.total", null, locale));
			tituloConFiltro.append(":" + tab);
			tituloConFiltro.append(filtro.getTotal());
		}
		if (filtro.getTipodocumento() != null) {
			tituloConFiltro.append(tab);
			tituloConFiltro.append(this.appMessageSource
					.getMessage("titulo.tipodocpre", null, locale));
			tituloConFiltro.append(":" + tab);
			tituloConFiltro.append(filtro.getTipodocumento());
		}
		if (filtro.getModalies() != null) {
			tituloConFiltro.append(tab);
			tituloConFiltro.append(this.appMessageSource
					.getMessage("titulo.tipoorgpre", null, locale));
			tituloConFiltro.append(":" + tab);
			tituloConFiltro.append(filtro.getModalies());
		}
		if (filtro.getAuditoria() != null) {
			tituloConFiltro.append(tab);
			tituloConFiltro.append(this.appMessageSource
					.getMessage("titulo.auditoria", null, locale));
			tituloConFiltro.append(":" + tab);
			tituloConFiltro.append(filtro.getAuditoria());
		}

		return tituloConFiltro.toString();
	}

	/**
	 * MÃ©todo para convertir la lista de Datos antes creada a un String y
	 * pasarlo como JSON a el web service.
	 * 
	 * listaInforme List<HashMap<String, String>> String
	 *
	 * @param listaInforme
	 *            the lista informe
	 * @return the string
	 * @throws JsonGenerationException
	 *             JsonGenerationException
	 * @throws JsonMappingException
	 *             JsonMappingException
	 * @throws IOException
	 *             IOException
	 */
	private String convertirJson(List<HashMap<String, String>> listaInforme)
			throws JsonGenerationException, JsonMappingException, IOException {

		String json = null;
		ObjectMapper objMapper = new ObjectMapper();
		json = objMapper.writeValueAsString(listaInforme);

		return json;
	}

	/**
	 * MÃ©todo para convertir la lista de Grupos antes creada a un String y
	 * pasarlo como JSON a el web service.
	 * 
	 * listaGrupos List<Grupo> String
	 *
	 * @param listaGrupos
	 *            the lista grupos
	 * @return the string
	 * @throws JsonGenerationException
	 *             JsonGenerationException
	 * @throws JsonMappingException
	 *             JsonMappingException
	 * @throws IOException
	 *             IOException
	 */
	private String convertirJsonGr(List<Grupo> listaGrupos)
			throws JsonGenerationException, JsonMappingException, IOException {

		String json = null;
		ObjectMapper objMapper = new ObjectMapper();
		json = objMapper.writeValueAsString(listaGrupos);

		return json;
	}

	/**
	 * Inicializar hm datos fila.
	 * 
	 * HashMap
	 *
	 * @return the hash map
	 */
	public HashMap<String, String> inicializarHmDatosFila() {
		return new HashMap<String, String>();
	}

	/**
	 * MÃ©todo para crear la definiciÃ³n del pie de pÃ¡gina (String text1,
	 * String text2, String text3, Integer tam).
	 * 
	 * DefinicionPie
	 *
	 * @return the definicion pie
	 * @throws AB04BException
	 *             the AB 04 B exception
	 */
	private DefinicionPie setDefinicionPie() throws AB04BException {
		try {

			// String tituloDes =
			// this.k72CrearXMLInformeService.devolverPiePagina();
			String tituloDes = "";
			return new DefinicionPie("", tituloDes, "numpag", Constantes.CIEN);
		} catch (Exception e) {
			throw new AB04BException(e, e.getMessage());
		}
	}

	/**
	 * MÃ©todo para crear la definiciÃ³n de la pÃ¡gina (String orientacion,
	 * Integer tamanoLetra, String tamanoPag, String textoAdicional).
	 * 
	 * titulo String DefinicionPag
	 *
	 * @param titulo
	 *            the titulo
	 * @return the definicion pag
	 */
	private DefinicionPag setDefinicionPag(String titulo) {
		return new DefinicionPag(Orientacion.HORIZONTAL,

				Constantes.DIEZ, Tamano.A4, titulo);
	}

}
