package com.ejie.ab04b.util;

import java.io.IOException;
import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Enumeration;
import java.util.List;
import java.util.Vector;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.Font;
import org.apache.poi.ss.usermodel.IndexedColors;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.context.support.ReloadableResourceBundleMessageSource;
import org.springframework.ui.ModelMap;

import com.ejie.ab04b.constantes.Constantes;
import com.ejie.ab04b.report.SdfExcelStyle;
import com.ejie.ab04b.report.SdfReportData;
import com.ejie.x38.reports.ReportData;
import com.gfi.spring.ApplicationContextProvider;
import com.gfi.utils.UtilFiles;

/**
 * UtilidadesWar.
 * 
 * @author GFI
 * 
 */
public final class UtilidadesWar {

	private static final Logger LOGGER = LoggerFactory
			.getLogger(UtilidadesWar.class);

	/**
	 * Constructor de Utilidades.
	 */
	private UtilidadesWar() {
	}

	/**
	 * Caso de contener errores, estos serán devueltos en la response en formato
	 * String para ser tratados por el feedback de errores. No formato Json
	 * 
	 *  error
	 *            String
	 *  response
	 *            HttpServletResponse
	 *  boolean
	 *
	 * @param error the error
	 * @param response the response
	 * @return true, if successful
	 */
	public static boolean sendError(String error, HttpServletResponse response) {
		boolean hayErrores = false;
		if (error != null) {
			try {
				response.setContentType("application/json;charset=UTF-8");
				response.setCharacterEncoding(Constantes.ENCODING_UTF8);
				byte[] errorAux = error.getBytes(Constantes.ENCODING_UTF8);
				response.setStatus(HttpServletResponse.SC_NOT_ACCEPTABLE);
				response.setContentLength(errorAux.length);
				response.getOutputStream().write(errorAux);
				response.flushBuffer();
			} catch (IOException e) {
				UtilidadesWar.LOGGER.error("Error en el metodo sendError", e);
			}
			hayErrores = true;
		}
		return hayErrores;
	}

	/**
	 * Recoge el valor del parametro que acaba con el nombre especifiado.
	 * 
	 *  paramNameEnding
	 *            String
	 *  request
	 *            HttpServletRequest
	 *  String
	 *
	 * @param paramNameEnding the param name ending
	 * @param request the request
	 * @return the request param ends like
	 */
	public static String getRequestParamEndsLike(String paramNameEnding,
			HttpServletRequest request) {
		String resultado = null;
		@SuppressWarnings(value = "unchecked")
		Enumeration<String> parameters = request.getParameterNames();
		String auxName;
		while (parameters.hasMoreElements() && resultado == null) {
			auxName = parameters.nextElement();
			if (auxName.endsWith(paramNameEnding)) {
				resultado = request.getParameter(auxName);
			}
		}
		return resultado;
	}

	/**
	 * Carga un archivo en la response, para que se pueda descargar desde el
	 * navegador.
	 * 
	 *  filename
	 *            String
	 *  contenttype
	 *            String
	 *  size
	 *            long
	 *  inputcontent
	 *            InputStream
	 *  response
	 *            HttpServletResponse
	 *
	 * @param filename the filename
	 * @param contenttype the contenttype
	 * @param size the size
	 * @param inputcontent the inputcontent
	 * @param response the response
	 * @throws IOException             e
	 */
	public static void downloadFile(String filename, String contenttype,
			long size, InputStream inputcontent, HttpServletResponse response)
			throws IOException {
		UtilidadesWar.downloadFile(filename, null, contenttype, size,
				inputcontent, response);
	}

	/**
	 * Carga un archivo en la response, para que se pueda descargar desde el
	 * navegador.
	 * 
	 *  filename
	 *            String
	 *  extension
	 *            String
	 *  contenttype
	 *            String
	 *  size
	 *            long
	 *  inputcontent
	 *            InputStream
	 *  response
	 *            HttpServletResponse
	 *
	 * @param filename the filename
	 * @param extension the extension
	 * @param contenttype the contenttype
	 * @param size the size
	 * @param inputcontent the inputcontent
	 * @param response the response
	 * @throws IOException             e
	 */
	public static void downloadFile(String filename, String extension,
			String contenttype, long size, InputStream inputcontent,
			HttpServletResponse response) throws IOException {
		StringBuilder file = new StringBuilder();
		file.append(filename);
		if (extension != null) {
			file.append(".");
			file.append(extension);
		}
		if (UtilidadesWar.LOGGER.isTraceEnabled()) {
			StringBuilder traza = new StringBuilder();
			traza.append("downloadFile INI [");
			traza.append(file.toString()).append(", ");
			traza.append(contenttype).append(", ");
			traza.append(size).append(", ");
			traza.append(inputcontent).append(", ");
			traza.append(response).append("]");
			UtilidadesWar.LOGGER.trace(traza.toString());
		}

		if (size != 0) {
			if (size <= Integer.MAX_VALUE) {
				response.setContentLength((int) size);
			} else {
				response.addHeader("Content-Length", Long.toString(size));
			}
		}

		if (contenttype != null) {
			response.setContentType(contenttype);
		} else {
			response.setContentType("application/octet-stream");
		}

		response.setHeader("Content-Disposition", "attachment; filename=\""
				+ file.toString() + "\"");

		// Cookie para la descarga Ajax
		response.setHeader("Set-Cookie", "SGE_fileDownload=true; path=/");
		if (inputcontent != null) {
			UtilFiles.stream(inputcontent, response.getOutputStream());
		}
	}

	/**
	 * Carga los datos a mostrar en el fichero XLS.
	 * 
	 *  <T>
	 *            Tipo sobre el que se va a generar el informe
	 *  modelMap
	 *            ModelMap
	 *  title
	 *            Titulo del informe en la hoja.
	 *  columns
	 *            String
	 *  lista
	 *            List<EntidadesTransversales>
	 *
	 * @param <T> the generic type
	 * @param modelMap the model map
	 * @param title the title
	 * @param columns the columns
	 * @param lista the lista
	 */
	public static <T> void generateReport(ModelMap modelMap, String title,
			String columns, List<T> lista) {

		// Generamos la fecha en formato yyyyMMdd_HHmmss para meter en el nombre
		// del fichero
		String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss")
				.format(Calendar.getInstance().getTime());

		// Nombre fichero
		modelMap.put("fileName", "datosExcel_" + timeStamp);

		// Datos
		List<SdfReportData<T>> reportData = new ArrayList<SdfReportData<T>>();
		// Hoja 1
		SdfReportData<T> datosExcel = new SdfReportData<T>();
		// nombre hoja
		ReloadableResourceBundleMessageSource messageSource = ApplicationContextProvider
				.getBean(ReloadableResourceBundleMessageSource.class);

		datosExcel.setSheetName(messageSource.getMessage("exportacion.datos",
				null, null, LocaleContextHolder.getLocale()));
		// Titulo de la hoja
		datosExcel.setTitle(title);
		// cabeceras hoja
		datosExcel.setHeaderNames(ReportData.parseColumns(columns));
		// Estilos:
		SdfExcelStyle estiloTitle = new SdfExcelStyle(
				UtilidadesWar.EXCEL_FONT_NAME,
				UtilidadesWar.EXCEL_FONT_SIZE_TITLE, Font.BOLDWEIGHT_BOLD,
				IndexedColors.LIGHT_BLUE.index, IndexedColors.WHITE.index,
				CellStyle.ALIGN_CENTER);
		estiloTitle.setBorder(CellStyle.BORDER_THIN, CellStyle.BORDER_THIN,
				CellStyle.BORDER_THIN, CellStyle.BORDER_THIN,
				IndexedColors.GREY_50_PERCENT.index);
		SdfExcelStyle estiloHeader = new SdfExcelStyle(
				UtilidadesWar.EXCEL_FONT_NAME,
				UtilidadesWar.EXCEL_FONT_SIZE_HEADER, Font.BOLDWEIGHT_NORMAL,
				IndexedColors.WHITE.index, IndexedColors.LIGHT_BLUE.index,
				CellStyle.ALIGN_CENTER);
		estiloHeader.setBorder(CellStyle.BORDER_THIN, CellStyle.BORDER_THIN,
				CellStyle.BORDER_THIN, CellStyle.BORDER_THIN,
				IndexedColors.GREY_50_PERCENT.index);
		SdfExcelStyle estiloEven = new SdfExcelStyle(
				UtilidadesWar.EXCEL_FONT_NAME,
				UtilidadesWar.EXCEL_FONT_SIZE_DATA, Font.BOLDWEIGHT_NORMAL,
				IndexedColors.BLACK.index, IndexedColors.GREY_25_PERCENT.index,
				CellStyle.ALIGN_GENERAL);
		estiloEven.setBorder(CellStyle.BORDER_THIN, CellStyle.BORDER_THIN,
				CellStyle.BORDER_THIN, CellStyle.BORDER_THIN,
				IndexedColors.GREY_50_PERCENT.index);
		SdfExcelStyle estiloOdd = new SdfExcelStyle(
				UtilidadesWar.EXCEL_FONT_NAME,
				UtilidadesWar.EXCEL_FONT_SIZE_DATA, Font.BOLDWEIGHT_NORMAL,
				IndexedColors.BLACK.index, IndexedColors.WHITE.index,
				CellStyle.ALIGN_GENERAL);
		estiloOdd.setBorder(CellStyle.BORDER_THIN, CellStyle.BORDER_THIN,
				CellStyle.BORDER_THIN, CellStyle.BORDER_THIN,
				IndexedColors.GREY_50_PERCENT.index);

		datosExcel.setStyleTitleCell(estiloTitle);
		datosExcel.setStyleHeaderCell(estiloHeader);
		datosExcel.setStyleRowEvenCell(estiloEven);
		datosExcel.setStyleRowOddCell(estiloOdd);

		if (!Utilities.isEmptyList(lista)) {
			datosExcel.setModelData(lista);
		}
		reportData.add(datosExcel);
		modelMap.put("reportData", reportData);
	}

	/**
	 * Determina si alguno de los "Object" esta includio en el Vector.
	 * 
	 *  vector
	 *            Vector<Object>
	 *  elements
	 *            Object...
	 *  true/false
	 *
	 * @param vector the vector
	 * @param elements the elements
	 * @return true, if successful
	 */
	public static boolean vectorContieneElement(Vector<?> vector,
			Object... elements) {
		for (Object obj : elements) {
			if (vector.contains(obj)) {
				return true;
			}
		}
		return false;
	}

	private static final String EXCEL_FONT_NAME = "Verdana";
	private static final short EXCEL_FONT_SIZE_TITLE = (short) 350;
	private static final short EXCEL_FONT_SIZE_HEADER = (short) 210;
	private static final short EXCEL_FONT_SIZE_DATA = (short) 200;

}