/*
 * (c) Copyright 2001 MyCorporation.
 * All Rights Reserved.
 */
package com.visionnaire.report;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.StringReader;
import java.net.URL;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.sax.SAXSource;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;

import org.apache.fop.apps.Driver;
import org.apache.fop.apps.FOPException;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;

import com.visionnaire.web.filter.ByteArrayServletResponseWrapper;

/**
 * @version 	1.0
 * @author
 */
public class FopFilter implements Filter
{
	private PageConfiguration defaultConfiguration = new PageConfiguration();

	/*
	 * @see Filter#init(FilterConfig)
	 */
	public void init(FilterConfig arg0) throws ServletException
	{
		String aux;
		aux = arg0.getInitParameter("margin-right");
		if(aux != null && aux.length()>0)
			defaultConfiguration.setMarginRight(aux);
		aux = arg0.getInitParameter("margin-left");
		if(aux != null && aux.length()>0)
			defaultConfiguration.setMarginLeft(aux);
		aux = arg0.getInitParameter("margin-top");
		if(aux != null && aux.length()>0)
			defaultConfiguration.setMarginTop(aux);
		aux = arg0.getInitParameter("margin-bottom");
		if(aux != null && aux.length()>0)
			defaultConfiguration.setMarginBottom(aux);
		aux = arg0.getInitParameter("page-width");
		if(aux != null && aux.length()>0)
			defaultConfiguration.setPageWidth(aux);
		aux = arg0.getInitParameter("page-height");
		if(aux != null && aux.length()>0)
			defaultConfiguration.setPageHeight(aux);
	}


	/*
	 * @see Filter#doFilter(ServletRequest, ServletResponse, FilterChain)
	 */
	public void doFilter(
		ServletRequest req,
		ServletResponse res,
		FilterChain chain)
		throws IOException, ServletException
	{
		try
		{
			//Obtem o conteudo fo a partir da página JSP que está sendo chamada
			ByteArrayServletResponseWrapper wrapper =
				new ByteArrayServletResponseWrapper((HttpServletResponse) res);

			chain.doFilter(req, wrapper);
			
			String xmlContent = wrapper.toString();
			
			if ((xmlContent != null) && (xmlContent.length() != 0)) {
				//valida o conteúdo do arquivo de dados de acordo com o DTD
				ReportHandler reportHandler = new ReportHandler();
	            SAXParserFactory factory = SAXParserFactory.newInstance();
	            factory.setValidating(false);
	            SAXParser parser = factory.newSAXParser();
	            XMLReader reader = parser.getXMLReader();
	            reader.setErrorHandler(reportHandler);
	            reader.setEntityResolver(reportHandler);
	            
	            //faz a transformação dos dados para um arquivo no formato fo
				SAXSource xmlSource
					= new SAXSource(new InputSource(new StringReader(xmlContent)));
				xmlSource.setXMLReader(reader);
				
				URL theURL = getClass().getResource("/report.xsl");
				
				Source xslSource = new StreamSource(theURL.openStream());
				
				ByteArrayOutputStream out = new ByteArrayOutputStream();
	
				TransformerFactory tFactory = TransformerFactory.newInstance();
				Transformer transformer = tFactory.newTransformer(xslSource);
				
				//seta os parametros de página para os configurados no filtro
				//Primeiro passo: obtém as configurações da sessão do usuário
				PageConfiguration aux = null;
				HttpSession session = ((HttpServletRequest)req).getSession(false);
				if(session != null)
				{
					aux = (PageConfiguration)session.getAttribute("pageConfiguration");
					System.out.println("pegou da sessão");
					System.out.println(aux);
				}
				if(aux == null)
					aux = defaultConfiguration;
					
				transformer.setParameter("margin-right",aux.getMarginRightAsString());
				transformer.setParameter("margin-left",aux.getMarginLeftAsString());
				transformer.setParameter("margin-top",aux.getMarginTopAsString());
				transformer.setParameter("margin-bottom",aux.getMarginBottomAsString());
				transformer.setParameter("page-width",aux.getPageWidthAsString());
				transformer.setParameter("page-height",aux.getPageHeightAsString());
				
				
				transformer.transform(xmlSource, new StreamResult(out));
	           
	             
	
				//Obtém o stream da renderização PDF
				ByteArrayOutputStream pdfOut = new ByteArrayOutputStream();
				Driver driver = new Driver(new InputSource(new ByteArrayInputStream(out.toByteArray())), pdfOut);
				driver.setRenderer(Driver.RENDER_PDF);
				driver.run();
	
				res.setContentType("application/pdf");
	
				byte[] content = pdfOut.toByteArray();
				res.setContentLength(content.length);
				res.getOutputStream().write(content);
				res.getOutputStream().flush();
				
				driver.reset();
				pdfOut.close();
				out.close();
				wrapper.reset();
				res.getOutputStream().close();
			} else {
				((HttpServletResponse)res).setStatus(wrapper.getStatus());
			}
			
		}
		catch (FOPException e)
		{
			throw new ServletException(e);
		}
		catch(ParserConfigurationException e)
		{
			throw new ServletException(e);
		}
		catch(SAXException e)
		{
			throw new ServletException(e);
		}
		catch(TransformerConfigurationException e)
		{
			throw new ServletException(e);
		}
		catch(TransformerException e)
		{
			throw new ServletException(e);
		}

	}

	/*
	 * @see Filter#destroy()
	 */
	public void destroy()
	{
	}
	
}