package com.ejie.y41e.service;

import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import java.util.Map;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang.StringUtils;
import org.apache.poi.ss.usermodel.ClientAnchor;
import org.apache.poi.ss.usermodel.CreationHelper;
import org.apache.poi.ss.usermodel.Drawing;
import org.apache.poi.ss.usermodel.Picture;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.ss.util.WorkbookUtil;
import org.apache.poi.util.IOUtils;
import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import com.ejie.y41e.common.Y41eConstants;
import com.ejie.y41e.model.excel.Y41eExcelCelda;
import com.ejie.y41e.model.excel.Y41eExcelEstilo;
import com.ejie.y41e.model.excel.Y41eExcelHoja;
import com.ejie.y41e.model.excel.Y41eExcelModel;

/**
 *  
 *
 */
@Service(value = "ExcelReportService")
public class Y41eExcelReportServiceImpl implements Y41eExcelReportService {

    /**
     * LOGGER: Logger.
     */
    private static final Logger LOGGER = LoggerFactory.getLogger(Y41eExcelReportServiceImpl.class);

    /**
     * Este metodo sirve para generar el EXCEL
     *
     * @param templateName
     *            La plantilla
     * @param excelModel
     *            El modelo del PDF
     * @param response
     *            HttpServletResponse
     */
    @Override()
    public void generarExcel(String templateName, Y41eExcelModel excelModel, HttpServletResponse response) {
        try {

            String propiedad = System.getProperty("java.awt.headless");
            Y41eExcelReportServiceImpl.LOGGER.info("EXCEL propiedad de servidor [java.awt.headless]: " + propiedad);

            // Generar el libro y los estilos del libro.
            XSSFWorkbook libro = this.crearLibro(templateName, excelModel);
            // Escribimos el Excel en la response.
            this.writeResponse(templateName, response, libro);

        } catch (Exception e) {
            Y41eExcelReportServiceImpl.LOGGER.error(e.getMessage(), e);
        }
    }

    /**
     * @param templateName
     *            String
     * @param excelModel
     *            ExcelModel
     * @return crearLibro
     * @throws IOException
     *             IOException
     */
    private XSSFWorkbook crearLibro(String templateName, Y41eExcelModel excelModel) throws IOException {

        XSSFWorkbook libro = new XSSFWorkbook();
        this.procesarHojas(libro, excelModel.getListaHojas());
        // primera hoja activa
        libro.setSelectedTab(0);
        return libro;
    }

    /**
     * @param libro
     *            XSSFWorkbook
     * @param listaHojas
     *            List
     * @throws IOException
     *             IOException
     */
    private void procesarHojas(XSSFWorkbook libro, List<Y41eExcelHoja> listaHojas) throws IOException {

        if (!listaHojas.isEmpty()) {
            for (Y41eExcelHoja excelHoja : listaHojas) {
                String nombre = WorkbookUtil.createSafeSheetName(excelHoja.getNombreHoja());
                final XSSFSheet hoja = libro.createSheet(nombre);
                this.procesarParametros(libro, hoja, excelHoja.getParametros());
            }
        } else {
            libro.createSheet();
        }
    }

    /**
     * @param libro
     *            XSSFWorkbook
     * @param hoja
     *            XSSFSheet
     * @param parametros
     *            Map
     * @throws IOException
     *             e
     */
    private void procesarParametros(XSSFWorkbook libro, XSSFSheet hoja, Map<String, Y41eExcelCelda> parametros)
            throws IOException {

        for (String key : parametros.keySet()) {
            final Y41eExcelCelda y41eCelda = parametros.get(key);

            if (y41eCelda.getTipoCelda().equals(Y41eConstants.TIPO_CELDA_IMAGEN)) {
                InputStream is = Y41eExcelReportServiceImpl.class.getResourceAsStream(y41eCelda.getRutaImagen());
                byte[] bytes = IOUtils.toByteArray(is);
                int pictureIdx = libro.addPicture(bytes, Workbook.PICTURE_TYPE_JPEG);
                is.close();
                CreationHelper helper = libro.getCreationHelper();
                Drawing drawing = hoja.createDrawingPatriarch();
                ClientAnchor anchor = helper.createClientAnchor();
                anchor.setCol1(y41eCelda.getPosicionX());
                anchor.setRow1(y41eCelda.getPosicionY());
                Picture pict = drawing.createPicture(anchor, pictureIdx);
                pict.resize();
            } else {
                // Obtenemos la fila y celda.
                XSSFRow fila = hoja.getRow(y41eCelda.getPosicionY());
                if (fila == null) {
                    fila = hoja.createRow(y41eCelda.getPosicionY());
                }
                XSSFCell celda = fila.getCell(y41eCelda.getPosicionX());
                if (celda == null) {
                    celda = fila.createCell(y41eCelda.getPosicionX());
                }

                // Ponemos el tipo de celda.
                celda.setCellType(XSSFCell.CELL_TYPE_STRING);

                // Escribimos el valor de la celda.
                celda.setCellValue(y41eCelda.getDato());

                // Estilo
                if (StringUtils.isNotBlank(y41eCelda.getEstilo())) {
                    celda.setCellStyle(Y41eExcelEstilo.getEstilo(libro, y41eCelda.getEstilo()));
                }

                // Activamos la celda
                celda.setAsActiveCell();
                if(y41eCelda.getAnchoMerge()>0){
                    hoja.addMergedRegion(new CellRangeAddress(y41eCelda.getPosicionY(), y41eCelda.getPosicionY(), y41eCelda.getPosicionX(),
                            y41eCelda.getPosicionX()+y41eCelda.getAnchoMerge()));
                }
                if(y41eCelda.getAlto()>0){
                    celda.getRow().setHeight((short)y41eCelda.getAlto());
                    celda.getCellStyle().setWrapText(true);
                }
            }

        }
    }

    /**
     * @param templateName
     *            String
     * @param nombre
     *            String
     * @param response
     *            HttpServletResponse
     * @param libro
     *            XSSFWorkbook
     * @throws IOException
     *             IOException
     */
    private void writeResponse(String templateName, HttpServletResponse response, XSSFWorkbook libro)
            throws IOException {

        Cookie cookie = new Cookie("fileDownload", "true");
        cookie.setPath("/");
        response.addCookie(cookie);
        response.getOutputStream().close();
        response.setHeader("Pragma", "cache");
        response.setHeader("Expires", "0");
        response.setHeader("Cache-Control", "private");
        // Content
        response.setContentType(Y41eConstants.CONTENT_TYPE_EXCEL);
        // Nombre Fichero
        response.setHeader("Content-Disposition", "attachment; filename=\"" + templateName + ".xlsx" + "\"");

        // Flush byte array to servlet output stream.
        ServletOutputStream out = response.getOutputStream();
        out.flush();
        libro.write(out);
        out.flush();
    }
}
