package com.ejie.ab79.service.actuaciones;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.List;
import java.util.Locale;

import javax.activation.MimetypesFileTypeMap;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;

import org.apache.poi.hssf.usermodel.HSSFCellStyle;
import org.apache.poi.hssf.usermodel.HSSFFont;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.Font;
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.ab79.comun.Constantes;
import com.ejie.ab79.dao.actuaciones.ResultadosActuacionDao;
import com.ejie.ab79.model.actuaciones.ResultadosActuacion;
import com.ejie.x38.dto.JerarquiaDto;
import com.ejie.x38.dto.TableRequestDto;
import com.ejie.x38.dto.TableResponseDto;
import com.ejie.x38.dto.TableRowDto;

/**
 * ResultadosActuacionServiceImpl  
 * 
 *  
 */

@Service(value = "resultadosActuacionService")
public class ResultadosActuacionServiceImpl implements ResultadosActuacionService {

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

	@Autowired
	private ResultadosActuacionDao resultadosActuacionDao;

	@Resource
	private ReloadableResourceBundleMessageSource appMessageSource;

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

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

	/**
	 * Finds a single row in the ResultadosActuacion table.
	 *
	 * @param resultadosActuacion
	 *            ResultadosActuacion
	 * @return ResultadosActuacion
	 */
	public ResultadosActuacion find(ResultadosActuacion resultadosActuacion) {
		return this.resultadosActuacionDao.find(resultadosActuacion);
	}

	@Override
	public Integer findRegistroDuplicado(ResultadosActuacion resultadoActuacion) {
		return this.resultadosActuacionDao.findRegistroDuplicado(resultadoActuacion);
	}

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

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

	@Override
	public List<ResultadosActuacion> findAllREST(ResultadosActuacion filterResultadosActuacion,
			TableRequestDto tableRequestDto) {
		return this.resultadosActuacionDao.findAllREST(filterResultadosActuacion, tableRequestDto);
	}

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

	/*
	 * OPERACIONES RUP_TABLE
	 */

	/**
	 * Removes rows from the ResultadosActuacion table.
	 *
	 * @param filterResultadosActuacion
	 *            ResultadosActuacion
	 * @param tableRequestDto
	 *            TableRequestDto
	 * @param startsWith
	 *            Boolean
	 */
	public void removeMultiple(ResultadosActuacion filterResultadosActuacion, TableRequestDto tableRequestDto,
			Boolean startsWith) {
		this.resultadosActuacionDao.removeMultiple(filterResultadosActuacion, tableRequestDto, startsWith);
	}

	/**
	 * Filter method in the ResultadosActuacion table.
	 *
	 * @param filterResultadosActuacion
	 *            ResultadosActuacion
	 * @param tableRequestDto
	 *            TableRequestDto
	 * @param startsWith
	 *            Boolean
	 * @return TableResponseDto<ResultadosActuacion>
	 */
	public TableResponseDto<ResultadosActuacion> filter(ResultadosActuacion filterResultadosActuacion,
			TableRequestDto tableRequestDto, Boolean startsWith) {
		List<ResultadosActuacion> listaResultadosActuacion = this.resultadosActuacionDao
				.findAllLike(filterResultadosActuacion, tableRequestDto, false);
		Long recordNum = this.resultadosActuacionDao.findAllLikeCount(
				filterResultadosActuacion != null ? filterResultadosActuacion : new ResultadosActuacion(), false);

		TableResponseDto<ResultadosActuacion> usuarioDto = new TableResponseDto<ResultadosActuacion>(tableRequestDto,
				recordNum, listaResultadosActuacion);

		if (tableRequestDto.getMultiselection().getSelectedIds() != null) {
			List<TableRowDto<ResultadosActuacion>> reorderSelection = this.resultadosActuacionDao
					.reorderSelection(filterResultadosActuacion, 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<ResultadosActuacion>> reorderSeeker = this.resultadosActuacionDao
					.reorderSelection(filterResultadosActuacion, tableRequestDto, startsWith);
			usuarioDto.setReorderedSeeker(reorderSeeker);
			usuarioDto.addAdditionalParam("reorderedSeeker", reorderSeeker);
		}
		return usuarioDto;
	}

	/**
	 * Searches rows in the ResultadosActuacion table.
	 *
	 * @param filterResultadosActuacion
	 *            ResultadosActuacion
	 * @param searchResultadosActuacion
	 *            ResultadosActuacion
	 * @param tableRequestDto
	 *            TableRequestDto
	 * @param startsWith
	 *            Boolean
	 * @return List<TableRowDto<ResultadosActuacion>>
	 */
	public List<TableRowDto<ResultadosActuacion>> search(ResultadosActuacion filterResultadosActuacion,
			ResultadosActuacion searchResultadosActuacion, TableRequestDto tableRequestDto, Boolean startsWith) {
		return this.resultadosActuacionDao.search(filterResultadosActuacion, searchResultadosActuacion, tableRequestDto,
				startsWith);
	}

	/**
	 * Reorder the selection made in ResultadosActuacion table.
	 *
	 * @param filterResultadosActuacion
	 *            ResultadosActuacion
	 * @param tableRequestDto
	 *            TableRequestDto
	 * @param startsWith
	 *            Boolean
	 * @return Object
	 */
	public Object reorderSelection(ResultadosActuacion filterResultadosActuacion, TableRequestDto tableRequestDto,
			Boolean startsWith) {
		return this.resultadosActuacionDao.reorderSelection(filterResultadosActuacion, tableRequestDto, startsWith);
	}

	/*
	 * OPERACIONES RUP_TABLE JERARQUIA
	 */

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

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

	/**
	 * Exporta Datos al clipBoard
	 *
	 */
	public List<ResultadosActuacion> getMultiple(ResultadosActuacion filterResultadosActuacion,
			TableRequestDto tableRequestDto, Boolean startsWith) {
		return this.resultadosActuacionDao.getMultiple(filterResultadosActuacion, tableRequestDto, startsWith);
	}

	@Override
	public void getExcel(List<ResultadosActuacion> listaResultadosActuacion, HttpServletResponse response) {

		Locale locale = LocaleContextHolder.getLocale();

		boolean euskera = false;

		if (locale.toString().equals(Constantes.EUSKERA)) {
			euskera = true;
		}

		try {

			// Nombre del archivo
			String fileName = appMessageSource.getMessage("excel.resultadosActuacion.sheetName", null, locale) + ".xls";

			// Creamos la hoja
			HSSFWorkbook workbook = new HSSFWorkbook();
			HSSFSheet sheet = workbook
					.createSheet(appMessageSource.getMessage("excel.resultadosActuacion.sheetName", null, locale));

			// Definimos los estilos y fuentes de la hoja
			HSSFFont font = workbook.createFont();
			font.setFontName(HSSFFont.FONT_ARIAL);
			font.setFontHeightInPoints((short) 12);
			font.setBoldweight(Font.BOLDWEIGHT_BOLD);

			HSSFCellStyle headerStyle = workbook.createCellStyle();
			headerStyle.setBorderBottom(CellStyle.BORDER_MEDIUM);
			headerStyle.setFont(font);
			headerStyle.setAlignment(CellStyle.ALIGN_CENTER);

			HSSFCellStyle disabledStyle = workbook.createCellStyle();
			disabledStyle.setFillPattern(CellStyle.THIN_FORWARD_DIAG);

			// Creamos la fila cabecera
			HSSFRow rowHead = sheet.createRow(0);

			rowHead.createCell(0)
					.setCellValue(appMessageSource.getMessage("excel.resultadosActuacion.descripcion", null, locale));
			rowHead.createCell(1)
					.setCellValue(appMessageSource.getMessage("excel.resultadosActuacion.direccion", null, locale));
			rowHead.createCell(2)
					.setCellValue(appMessageSource.getMessage("excel.resultadosActuacion.origen", null, locale));

			rowHead.getCell(0).setCellStyle(headerStyle);
			rowHead.getCell(1).setCellStyle(headerStyle);
			rowHead.getCell(2).setCellStyle(headerStyle);

			// Creamos el resto de filas con sus celdas
			int rowCount = 1;
			for (ResultadosActuacion resAct : listaResultadosActuacion) {

				HSSFRow resActRow = sheet.createRow(rowCount++);

				resActRow.createCell(0).setCellValue((euskera) ? resAct.getDesResAct().getDescripcionEuskera()
						: resAct.getDesResAct().getDescripcionCastellano());
				resActRow.createCell(1).setCellValue((euskera) ? resAct.getDireccion().getDescripcionEuskera()
						: resAct.getDireccion().getDescripcionCastellano());
				resActRow.createCell(2).setCellValue((euskera) ? resAct.getOrigenesInspeccion().getDescripcionEuskera()
						: resAct.getOrigenesInspeccion().getDescripcionCastellano());
			}

			// Anchura de las columnas
			sheet.autoSizeColumn(0);
			sheet.autoSizeColumn(1);
			sheet.autoSizeColumn(2);

			FileOutputStream fileOut = new FileOutputStream(fileName);
			workbook.write(fileOut);
			fileOut.close();

			ResultadosActuacionServiceImpl.logger.info("[GET - exportarExcel] : Archivo generado");

			// Creamos el archivo a descargar
			File fileToDownload = new File(fileName);
			InputStream in = new FileInputStream(fileToDownload);

			// Recogemos el MIME type del fichero
			String mimeType = new MimetypesFileTypeMap().getContentType(fileName);

			if (mimeType == null) {
				// Si no se encuentra lo seteamos manualmente
				mimeType = "application/octet-stream";
			}
			ResultadosActuacionServiceImpl.logger.info("[GET - exportarExcel] : MIME type: " + mimeType);

			// Seteamos el contentType de la response
			response.setContentType(mimeType);
			response.setContentLength((int) fileToDownload.length());

			// Descargamos el archivo
			response.setHeader("Content-Disposition", "attachment; filename=\"" + fileToDownload.getName() + "\"");

			// Obtenemos el outputStream de la response
			OutputStream outStream = response.getOutputStream();

			byte[] buffer = new byte[4096];
			int bytesRead = -1;

			while ((bytesRead = in.read(buffer)) != -1) {
				outStream.write(buffer, 0, bytesRead);
			}

			// Cerramos el InputStream y el OutputStream
			in.close();
			outStream.close();

			ResultadosActuacionServiceImpl.logger.info("[GET - exportarExcel] : Archivo descargado con �xito");

		} catch (Exception e) {
			ResultadosActuacionServiceImpl.logger.error(e.getMessage());
		}
	}

}
