package com.questdiagnostics.applications.resultview.servlet;

import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
import org.xml.sax.InputSource;
import org.xml.sax.XMLReader;
import org.apache.fop.apps.Driver;
import org.apache.fop.apps.Version;
import com.questdiagnostics.applications.resultview.datanavigation.SessionReportData;

public class ReportGeneratorServlet extends HttpServlet {
 
  java.util.Properties reportProps;
  org.apache.xalan.serialize.Serializer serializer;
  String foOutputFilename, xmlOutputFilename;
  HttpSession session;
  boolean isIE4;
  
  public void init() {
    foOutputFilename    = "ReportOutput.fo";
    xmlOutputFilename   = "ReportOutput.xml";

    reportProps = new java.util.Properties();
    reportProps.setProperty("report1001", "lr");
    reportProps.setProperty("report1007", "lr");
    reportProps.setProperty("report1006", "fr");
    reportProps.setProperty("report1009", "ss");
    reportProps.setProperty("report1011", "pvh");
    reportProps.setProperty("report1012", "ps"); 
    reportProps.setProperty("report1014", "na");

    reportProps.setProperty("htmlContentType", "Html");
    reportProps.setProperty("pdfContentType", "Fo");

    reportProps.setProperty("htmlHeaderContentString", "text/html");
    reportProps.setProperty("pdfHeaderContentString", "application/pdf");

    serializer = org.apache.xalan.serialize.SerializerFactory.getSerializer(
                  org.apache.xalan.templates.OutputProperties.getDefaultMethodProperties("xml"));
  }
  
  public void service(HttpServletRequest request, HttpServletResponse response) throws ServletException {

    String contentType="";
    String headerContentString="";
    session = request.getSession();
    isIE4 = false;
    
    System.out.println("servlet: session ID = " + session.getId()); 
    System.out.println("ReportGeneratorServlet says hi - " + new java.util.Date().toString());

    try {
          
      if ( session.getAttribute("sessionReportObject") != null ) {
 
        String userAgent = request.getHeader("User-Agent").toLowerCase();
        String counter = request.getParameter("counter");
        String previousCounter = (String)session.getAttribute("report_counter");
        isIE4 = (userAgent.indexOf("msie 4") != -1);
        
        String headerParameterName;
        for (java.util.Enumeration e = request.getHeaderNames(); e.hasMoreElements();) {
          headerParameterName = (String)e.nextElement();
          System.out.println("request.getHeader(" + headerParameterName + ") = " + request.getHeader(headerParameterName)); 
        }

        SessionReportData srd = (SessionReportData)session.getAttribute("sessionReportObject");
        
        System.out.println("counter = "   + counter); 
        System.out.println("previousCounter = "   + previousCounter); 
        System.out.println("srd.contentType = "   + srd.contentType); 
        System.out.println("srd.reportId = "      + srd.reportId); 
				System.out.println("reportProps.getProperty(report" + srd.reportId + ") = " + reportProps.getProperty("report" + srd.reportId));

        contentType         = reportProps.getProperty(srd.contentType + "ContentType");    
        headerContentString = reportProps.getProperty(srd.contentType + "HeaderContentString");    

        if ( contentType.equals("Fo") && userAgent.equals("contype") )  {
            response.setContentType(headerContentString); 
        }
        // functionality to check for same report called back to back
        // (IE 4.x calls PDF docs multiple times)
        else if (   isIE4 
                 && contentType.equals("Fo") 
                 && counter.equals(previousCounter) 
                 && (session.getAttribute("report_content") != null) 
                ) {
          System.out.println("\nReturning cached report\n");    
          outputPdf( (byte[])session.getAttribute("report_content"), response );
        }
        else {
          renderReport(reportProps.getProperty("report" + srd.reportId), contentType, srd.reportDom, response);
        }
        
        session.setAttribute("report_counter", counter);
      }

      else {
        PrintWriter out = response.getWriter();
        out.println("<html><head><title>Error</title></head>\n"+
                    "<body><h1>ReportGeneratorServlet Error 3</h1><h3>No 'fo' "+
                    "request param given.</body></html>");
      }
    } 
    catch (ServletException ex) { throw ex; }
    catch (Exception ex) { throw new ServletException(ex); }
  }

  void renderReport(String reportName, String contentType, 
                    org.w3c.dom.Document xmlDoc, HttpServletResponse response) throws ServletException {
    try {

      System.out.println("reportName = " + reportName);
      
      String xsltFilename  = getServletConfig().getServletContext().getAttribute("XSLTPathPrefix")	
                         + reportName + "_XmlTo" + contentType + ".xsl";
      File xsltFile = new File(xsltFilename);

/*
        System.out.println("f.getAbsolutePath()  = " + f.getAbsolutePath()  );
        System.out.println("f.getCanonicalPath() = " + f.getCanonicalPath() );
        System.out.println("f.getName()          = " + f.getName()          );
        System.out.println("f.getParent()        = " + f.getParent()        );
        System.out.println("f.getPath()          = " + f.getPath()          );
        System.out.println("f.toString()         = " + f.toString()         );
*/

// output XML for debugging
/*
      File f = new File(xmlOutputFilename);
      FileOutputStream fos = new FileOutputStream(f);
      System.out.println("Writing XML source to: " + f.getAbsolutePath() + "\n");
      serializer.setOutputStream(fos);
      serializer.asDOMSerializer().serialize(xmlDoc);
      fos.close();
*/
      javax.xml.parsers.DocumentBuilderFactory dFactory = javax.xml.parsers.DocumentBuilderFactory.newInstance();
      dFactory.setNamespaceAware(true);
      javax.xml.parsers.DocumentBuilder dBuilder = dFactory.newDocumentBuilder();
  
      javax.xml.transform.dom.DOMSource xmlDomSource = new javax.xml.transform.dom.DOMSource(xmlDoc);
  
      org.w3c.dom.Document xslDoc = dBuilder.parse(xsltFile);
      javax.xml.transform.dom.DOMSource xslDomSource = new javax.xml.transform.dom.DOMSource(xslDoc);
  
      javax.xml.transform.TransformerFactory tFactory = javax.xml.transform.TransformerFactory.newInstance();
      javax.xml.transform.Templates templates = tFactory.newTemplates(xslDomSource);
      javax.xml.transform.Transformer transformer = templates.newTransformer();
  
      if ( contentType.equals("Fo") ) { 
        renderPdf(xmlDomSource, transformer, response); 
      }
      else { 
        renderHtml(xmlDomSource, transformer, response);
      }
    } 
     catch (Exception ex) { throw new ServletException(ex); }
  }
  
  void renderHtml(javax.xml.transform.dom.DOMSource xml, javax.xml.transform.Transformer transformer,
                       HttpServletResponse response) throws ServletException {
    try {
      response.setContentType("text/html");
      PrintWriter out = response.getWriter();

      javax.xml.transform.stream.StreamResult streamResult = new javax.xml.transform.stream.StreamResult(out);
      transformer.transform(xml, streamResult);
    } 
    catch (Exception ex) { throw new ServletException(ex); }

  }

  void renderPdf(javax.xml.transform.dom.DOMSource xml, javax.xml.transform.Transformer transformer,
                       HttpServletResponse response) throws ServletException {
    try {
      javax.xml.transform.dom.DOMResult foDomResult = new javax.xml.transform.dom.DOMResult();
      transformer.transform(xml, foDomResult);

      org.w3c.dom.Document foDoc = (org.w3c.dom.Document)foDomResult.getNode();

// output FO for debugging
/*
      File f = new File(foOutputFilename);
      FileOutputStream fos = new FileOutputStream(f);
      System.out.println("Writing FO source to: " + f.getAbsolutePath() + "\n");
      serializer.setOutputStream(fos);
      serializer.asDOMSerializer().serialize(foDoc);
      fos.close();
*/

      ByteArrayOutputStream out = new ByteArrayOutputStream();

      org.apache.fop.apps.Driver driver = new org.apache.fop.apps.Driver();
      driver.setErrorDump(true);
      driver.setRenderer(driver.RENDER_PDF);
      driver.setupDefaultMappings() ;
	    driver.setOutputStream(out);
      driver.render(foDoc);

      byte[] content = out.toByteArray();

      // if browser is IE 4.x and report is generated for the first time, cache PDF byte array in session
      if (isIE4) {
        session.setAttribute("report_content", content);
      }

      outputPdf(content, response);
    } 
    catch (Exception ex) { throw new ServletException(ex); }
  }

  void outputPdf(byte[] content, HttpServletResponse response) throws ServletException {
    try {
      response.setContentType("application/pdf");
      response.setContentLength(content.length);
      System.out.println("Content length = " + content.length + "\n");
      response.getOutputStream().write(content);
      response.getOutputStream().flush();
    }
    catch (Exception ex) { throw new ServletException(ex); }
  }
}

