package com.ejie.ab79.service;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Calendar;
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.dao.InspectoresDao;
import com.ejie.ab79.model.Inspectores;
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 = "inspectoresService")
public class InspectoresServiceImpl implements InspectoresService {

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

	@Autowired
	private InspectoresDao inspectoresDao;

	@Resource
	private ReloadableResourceBundleMessageSource appMessageSource;

	@Transactional(rollbackFor = Throwable.class)
	public Inspectores add(Inspectores inspectores) {
		Calendar cal = Calendar.getInstance();
		inspectores.setFechaRegistro(cal.getTime());
		return this.inspectoresDao.add(inspectores);
	}

	@Transactional(rollbackFor = Throwable.class)
	public Inspectores update(Inspectores inspectores) {
		return this.inspectoresDao.update(inspectores);
	}

	public Inspectores find(Inspectores inspectores) {
		return this.inspectoresDao.find(inspectores);
	}

	@Transactional(rollbackFor = Throwable.class)
	public void remove(Inspectores inspectores) {
		this.inspectoresDao.remove(inspectores);
	}

	public List<Inspectores> findAll(Inspectores inspectores, TableRequestDto tableRequestDto) {
		return this.inspectoresDao.findAll(inspectores, tableRequestDto);
	}

	public List<Inspectores> findAllLike(Inspectores inspectores, TableRequestDto tableRequestDto, Boolean startsWith) {
		return this.inspectoresDao.findAllLike(inspectores, tableRequestDto, startsWith);
	}

	public void removeMultiple(Inspectores filterInspectores, TableRequestDto tableRequestDto, Boolean startsWith) {
		this.inspectoresDao.removeMultiple(filterInspectores, tableRequestDto, startsWith);
	}

	public TableResponseDto<Inspectores> filter(Inspectores filterInspectores, TableRequestDto tableRequestDto,
			Boolean startsWith) {
		List<Inspectores> listaInspectores = this.inspectoresDao.findAllLike(filterInspectores, tableRequestDto, false);
		Long recordNum = this.inspectoresDao
				.findAllLikeCount(filterInspectores != null ? filterInspectores : new Inspectores(), false);

		TableResponseDto<Inspectores> usuarioDto = new TableResponseDto<Inspectores>(tableRequestDto, recordNum,
				listaInspectores);

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

	public List<TableRowDto<Inspectores>> search(Inspectores filterInspectores, Inspectores searchInspectores,
			TableRequestDto tableRequestDto, Boolean startsWith) {
		return this.inspectoresDao.search(filterInspectores, searchInspectores, tableRequestDto, startsWith);
	}

	public Object reorderSelection(Inspectores filterInspectores, TableRequestDto tableRequestDto, Boolean startsWith) {
		return this.inspectoresDao.reorderSelection(filterInspectores, tableRequestDto, startsWith);
	}

	public TableResponseDto<JerarquiaDto<Inspectores>> jerarquia(Inspectores filterInspectores,
			TableRequestDto tableRequestDto, Boolean startsWith) {
		List<JerarquiaDto<Inspectores>> listaInspectores = this.inspectoresDao.findAllLikeJerarquia(filterInspectores,
				tableRequestDto);
		Long recordNum = this.inspectoresDao.findAllLikeCountJerarquia(filterInspectores, tableRequestDto);
		return new TableResponseDto<JerarquiaDto<Inspectores>>(tableRequestDto, recordNum, listaInspectores);
	}

	public TableResponseDto<JerarquiaDto<Inspectores>> jerarquiaChildren(Inspectores filterInspectores,
			TableRequestDto tableRequestDto) {
		TableResponseDto<JerarquiaDto<Inspectores>> tableResponseDto = new TableResponseDto<JerarquiaDto<Inspectores>>();
		tableResponseDto.addAdditionalParam(TableResponseDto.CHILDREN,
				this.inspectoresDao.findAllChild(filterInspectores, tableRequestDto));
		return tableResponseDto;
	}

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

	public Inspectores findByUsuarioXLNETS(Inspectores inspectores) {
		return this.inspectoresDao.findByUsuarioXLNETS(inspectores);
	}

	@Override
	public List<Inspectores> findTodosInspectores(Inspectores inspectores, TableRequestDto tableRequestDto) {
		return this.inspectoresDao.findTodosInspectores(inspectores, tableRequestDto);
	}

	@Override
	public Inspectores findByIdInspector(Inspectores inspectores) {
		return this.inspectoresDao.findByIdInspector(inspectores);
	}

	@Override
	public List<Inspectores> findAllREST(Inspectores filterInspectores) {
		return this.inspectoresDao.findAllREST(filterInspectores);
	}

	@Override
	public void getExcel(List<Inspectores> listaInspectores, HttpServletResponse response) {

		Locale locale = LocaleContextHolder.getLocale();

		try {

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

			// Creamos la hoja
			HSSFWorkbook workbook = new HSSFWorkbook();
			HSSFSheet sheet = workbook
					.createSheet(appMessageSource.getMessage("excel.inspectores.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.inspectores.dni", null, locale));
			rowHead.createCell(1)
					.setCellValue(appMessageSource.getMessage("excel.inspectores.nombreInspector", null, locale));
			rowHead.createCell(2)
					.setCellValue(appMessageSource.getMessage("excel.inspectores.numeroInspector", null, locale));
			rowHead.createCell(3)
					.setCellValue(appMessageSource.getMessage("excel.inspectores.usuarioXlnets", null, locale));
			rowHead.createCell(4).setCellValue(appMessageSource.getMessage("excel.inspectores.th", null, locale));

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

			// Creamos el resto de filas con sus celdas
			int rowCount = 1;
			for (Inspectores inspector : listaInspectores) {

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

				inspectorRow.createCell(0).setCellValue(inspector.getDni());
				inspectorRow.createCell(1).setCellValue(inspector.getNombreInspector());
				inspectorRow.createCell(2).setCellValue(inspector.getNumeroInspector());
				inspectorRow.createCell(3).setCellValue(inspector.getUsuarioXlnets());
				inspectorRow.createCell(4).setCellValue(inspector.getProvincia().getDsO());
			}

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

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

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

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

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

}
