package com.ejie.ab79.service.inspecciones;

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.inspecciones.EstadosInspeccionDao;
import com.ejie.ab79.model.inspecciones.DesEstIns;
import com.ejie.ab79.model.inspecciones.EstadosInspeccion;
import com.ejie.x38.dto.JerarquiaDto;
import com.ejie.x38.dto.TableRequestDto;
import com.ejie.x38.dto.TableResponseDto;
import com.ejie.x38.dto.TableRowDto;

@Service(value = "estadosInspeccionService")
public class EstadosInspeccionServiceImpl implements EstadosInspeccionService {

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

	@Autowired
	private EstadosInspeccionDao estadosInspeccionDao;

	@Resource
	private ReloadableResourceBundleMessageSource appMessageSource;

	@Transactional(rollbackFor = Throwable.class)
	public EstadosInspeccion add(EstadosInspeccion estadosInspeccion) {
		return this.estadosInspeccionDao.add(estadosInspeccion);
	}

	@Transactional(rollbackFor = Throwable.class)
	public EstadosInspeccion update(EstadosInspeccion estadosInspeccion) {
		return this.estadosInspeccionDao.update(estadosInspeccion);
	}

	public EstadosInspeccion find(EstadosInspeccion estadosInspeccion) {
		return this.estadosInspeccionDao.find(estadosInspeccion);
	}

	@Override
	public EstadosInspeccion findByOrigenDireccion(Integer idOrigenInspeccion, Integer idDireccion, Integer estado) {
		return this.estadosInspeccionDao.findByOrigenDireccion(idOrigenInspeccion, idDireccion, estado);
	}

	public EstadosInspeccion findDatosBasicos(EstadosInspeccion estadosInspeccion) {
		return this.estadosInspeccionDao.findDatosBasicos(estadosInspeccion);
	}

	@Override
	public Integer findRegistroDuplicado(EstadosInspeccion estadosInspeccion) {
		return this.estadosInspeccionDao.findRegistroDuplicado(estadosInspeccion);
	}

	@Transactional(rollbackFor = Throwable.class)
	public void remove(EstadosInspeccion estadosInspeccion) {
		this.estadosInspeccionDao.remove(estadosInspeccion);
	}

	public List<EstadosInspeccion> findAll(EstadosInspeccion estadosInspeccion, TableRequestDto tableRequestDto) {
		return this.estadosInspeccionDao.findAll(estadosInspeccion, tableRequestDto);
	}

	public List<EstadosInspeccion> findAllLike(EstadosInspeccion estadosInspeccion, TableRequestDto tableRequestDto,
			Boolean startsWith) {
		return this.estadosInspeccionDao.findAllLike(estadosInspeccion, tableRequestDto, startsWith);
	}

	public void removeMultiple(EstadosInspeccion filterEstadosInspeccion, TableRequestDto tableRequestDto,
			Boolean startsWith) {
		this.estadosInspeccionDao.removeMultiple(filterEstadosInspeccion, tableRequestDto, startsWith);
	}

	public TableResponseDto<EstadosInspeccion> filter(EstadosInspeccion filterEstadosInspeccion,
			TableRequestDto tableRequestDto, Boolean startsWith) {
		List<EstadosInspeccion> listaEstadosInspeccion = this.estadosInspeccionDao.findAllLike(filterEstadosInspeccion,
				tableRequestDto, false);
		Long recordNum = this.estadosInspeccionDao.findAllLikeCount(
				filterEstadosInspeccion != null ? filterEstadosInspeccion : new EstadosInspeccion(), false);

		TableResponseDto<EstadosInspeccion> usuarioDto = new TableResponseDto<EstadosInspeccion>(tableRequestDto,
				recordNum, listaEstadosInspeccion);

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

	public List<TableRowDto<EstadosInspeccion>> search(EstadosInspeccion filterEstadosInspeccion,
			EstadosInspeccion searchEstadosInspeccion, TableRequestDto tableRequestDto, Boolean startsWith) {
		return this.estadosInspeccionDao.search(filterEstadosInspeccion, searchEstadosInspeccion, tableRequestDto,
				startsWith);
	}

	public Object reorderSelection(EstadosInspeccion filterEstadosInspeccion, TableRequestDto tableRequestDto,
			Boolean startsWith) {
		return this.estadosInspeccionDao.reorderSelection(filterEstadosInspeccion, tableRequestDto, startsWith);
	}

	public TableResponseDto<JerarquiaDto<EstadosInspeccion>> jerarquia(EstadosInspeccion filterEstadosInspeccion,
			TableRequestDto tableRequestDto, Boolean startsWith) {
		List<JerarquiaDto<EstadosInspeccion>> listaEstadosInspeccion = this.estadosInspeccionDao
				.findAllLikeJerarquia(filterEstadosInspeccion, tableRequestDto);
		Long recordNum = this.estadosInspeccionDao.findAllLikeCountJerarquia(filterEstadosInspeccion, tableRequestDto);
		return new TableResponseDto<JerarquiaDto<EstadosInspeccion>>(tableRequestDto, recordNum,
				listaEstadosInspeccion);
	}

	public TableResponseDto<JerarquiaDto<EstadosInspeccion>> jerarquiaChildren(
			EstadosInspeccion filterEstadosInspeccion, TableRequestDto tableRequestDto) {
		TableResponseDto<JerarquiaDto<EstadosInspeccion>> tableResponseDto = new TableResponseDto<JerarquiaDto<EstadosInspeccion>>();
		tableResponseDto.addAdditionalParam(TableResponseDto.CHILDREN,
				this.estadosInspeccionDao.findAllChild(filterEstadosInspeccion, tableRequestDto));
		return tableResponseDto;
	}

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

	public List<EstadosInspeccion> findAllDatosInspeccion(EstadosInspeccion estadosInspeccion,
			TableRequestDto tableRequestDto) {
		return this.estadosInspeccionDao.findAllDatosInspeccion(estadosInspeccion, tableRequestDto);
	}

	@Override
	public List<EstadosInspeccion> findByDesResIns(DesEstIns desEstIns) {
		return this.estadosInspeccionDao.findByDesEstIns(desEstIns);
	}

	@Override
	public void getExcel(List<EstadosInspeccion> listaEstadosInspeccion, HttpServletResponse response) {

		Locale locale = LocaleContextHolder.getLocale();

		boolean euskera = false;

		// Configuramos variables de idioma.
		if (locale.toString().equals(Constantes.EUSKERA)) {
			euskera = true;
		}

		try {

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

			// Creamos la hoja
			HSSFWorkbook workbook = new HSSFWorkbook();
			HSSFSheet sheet = workbook
					.createSheet(appMessageSource.getMessage("excel.estadosInspeccion.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.estadosInspeccion.descripcion", null, locale));
			rowHead.createCell(1)
					.setCellValue(appMessageSource.getMessage("excel.estadosInspeccion.direccion", null, locale));
			rowHead.createCell(2)
					.setCellValue(appMessageSource.getMessage("excel.estadosInspeccion.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 (EstadosInspeccion estadosInspeccion : listaEstadosInspeccion) {

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

				estadosInspeccionRow.createCell(0)
						.setCellValue((euskera) ? estadosInspeccion.getDesEstIns().getDescripcionEuskera()
								: estadosInspeccion.getDesEstIns().getDescripcionCastellano());
				estadosInspeccionRow.createCell(1)
						.setCellValue((euskera) ? estadosInspeccion.getDireccion().getDescripcionEuskera()
								: estadosInspeccion.getDireccion().getDescripcionCastellano());
				estadosInspeccionRow.createCell(2)
						.setCellValue((euskera) ? estadosInspeccion.getOrigenInspeccion().getDescripcionEuskera()
								: estadosInspeccion.getOrigenInspeccion().getDescripcionCastellano());
			}

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

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

			EstadosInspeccionServiceImpl.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";
			}
			EstadosInspeccionServiceImpl.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();

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

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