package net.ihe.common.report;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.Serializable;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Map;
import javax.ejb.Remove;
import javax.ejb.Stateful;
import javax.faces.context.FacesContext;
import javax.persistence.EntityManager;
import javax.servlet.ServletContext;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
 

import net.ihe.gazelle.common.application.action.ApplicationPreferenceManager;
import net.ihe.gazelle.common.log.ExceptionLogging;
import net.sf.jasperreports.engine.JRAbstractExporter;
import net.sf.jasperreports.engine.JRException;
import net.sf.jasperreports.engine.JRExporterParameter;
import net.sf.jasperreports.engine.JRParameter;
import net.sf.jasperreports.engine.JasperFillManager;
import net.sf.jasperreports.engine.JasperPrint;
import net.sf.jasperreports.engine.JasperReport;
import net.sf.jasperreports.engine.export.JExcelApiExporter;
import net.sf.jasperreports.engine.export.JRCsvExporter;
import net.sf.jasperreports.engine.export.JRHtmlExporter;
import net.sf.jasperreports.engine.export.JRHtmlExporterParameter;
import net.sf.jasperreports.engine.export.JRPdfExporter;
import net.sf.jasperreports.engine.export.JRXmlExporter;
import net.sf.jasperreports.engine.util.SimpleFileResolver;
import net.sf.jasperreports.j2ee.servlets.BaseHttpServlet;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.impl.SessionFactoryImpl;
import org.jboss.seam.Component;
import org.jboss.seam.ScopeType;
import org.jboss.seam.annotations.Destroy;
import org.jboss.seam.annotations.In;
import org.jboss.seam.annotations.Logger;
import org.jboss.seam.annotations.Name;
import org.jboss.seam.annotations.Scope;
import org.jboss.seam.faces.FacesMessages;
import org.jboss.seam.log.Log;


@Stateful
@Scope(ScopeType.APPLICATION)
@Name("reportExporterManagerBean")
public class ReportExporterManager implements Serializable, ReportExporterManagerLocal
{
   
   /** Logger */
   @Logger
   private static Log log;

   /**
    * entityManager is the interface used to interact with the persistence
    * context.
    */
   @In
   private EntityManager entityManager;
   
   /**
    * Extract the filename from the full path of the name of the file
    * 
    * @param reportSource
    * @return the name of the file without the path.
    */
   private static String lastFileName( String reportSource )
   {
      int pos = reportSource.lastIndexOf(File.separatorChar) ;  
      if (pos == -1)
           return reportSource;
      else
         return reportSource.substring( pos ) ;
   }
   
 
   
   public String exportToJasperFlash( String reportSource    ) throws JRException
   {
     /* ServletContext servlet = (ServletContext) FacesContext.getCurrentInstance().getExternalContext().getContext() ;
     
      String applicationBaseName = ApplicationPreferenceManager.getApplicationUrlBaseName ( entityManager )  ;         

      String reportPath= reportSource;
      Map<String, Object> parameters= new HashMap<String, Object>() ;
      
      String reportDir=reportPath;
      String reportName = null ;
      int index=reportPath.lastIndexOf('/');
      if(index>0)
         {
          reportDir=reportPath.substring(0,index+1);
          reportName=reportPath.substring(index+1) ;
         }
      
          
      log.info("Report name : " + reportPath ) ; 
      JasperReport jasperReport;
      try
      {
         jasperReport = ReportRenderer.getJasperReport(reportPath);
         HashMap<String, Object> hashMap = new HashMap<String, Object>() ;
         hashMap.put("testingSessionId", new Integer(7)) ;
         parameters.put("BaseDir", reportDir);
 
         //Get current connection :
        
         Session s = (Session)entityManager.getDelegate() ;
         Connection c =   s.connection() ;
         
         JasperPrint jasperPrint=JasperFillManager.fillReport(jasperReport, parameters, c  );
         
         try{
            c.close() ;
            }
            catch ( Exception e ){
               e.printStackTrace() ;
            }
       //  JRHtmlExporter exporter=new JRHtmlExporter();
         
          servlet.setAttribute(BaseHttpServlet.DEFAULT_JASPER_PRINT_SESSION_ATTRIBUTE, jasperPrint);

        
       
        
         log.info("stop ID control ! :)") ;
         
         return "/administration/listSystemsForAllAIP.xhtml" ;
      }
      catch (FileNotFoundException e)
      {
        FacesMessages.instance().add(e.getMessage()) ;
        return "/home.xhtml" ;
      }
   */
      return null ;
    
   }
   /**
    * 
    */
   public void exportToPDF_(String reportSource, String fileNameDestination  ,  Map parameters  ) throws JRException
   {
      if ( parameters == null ) parameters = new HashMap<String, Object >() ;
      ReportExporterManager.exportToPDF( reportSource , fileNameDestination , parameters  ) ;
   }
   
   public void exportToPDF_(String reportSource, String fileNameDestination   ) throws JRException
   {
      HashMap<String, Object > parameters = new HashMap<String, Object >() ;
      ReportExporterManager.exportToPDF( reportSource , fileNameDestination , parameters  ) ;
   }
   
 
   /**
    * 
    * @param reportSource
    * @param fileNameDestination
    * @param parameters
    * @throws JRException
    */
   public static void exportToPDF(String reportSource, String fileNameDestination  ,  Map parameters  ) throws JRException
   {
      EntityManager em = (EntityManager)Component.getInstance("entityManager") ;
      JRPdfExporter exporter = new JRPdfExporter() ;
      exportToFormat(  reportSource, fileNameDestination  , parameters , em ,  exporter , "application/pdf" ) ;
   }
   
   
   public static void exportToCSV(String reportSource, String fileNameDestination  ,  Map parameters  ) throws JRException
   {
      EntityManager em = (EntityManager)Component.getInstance("entityManager") ;
      JRCsvExporter  exporter = new JRCsvExporter() ;
      exportToFormat(  reportSource, fileNameDestination  , parameters , em ,  exporter , "application/csv") ;
   }
   public static void exportToXLS(String reportSource, String fileNameDestination  ,  Map parameters  ) throws JRException
   {
      EntityManager em = (EntityManager)Component.getInstance("entityManager") ;
      JExcelApiExporter exporter = new JExcelApiExporter() ;
      exportToFormat(  reportSource, fileNameDestination  , parameters , em ,  exporter , "application/msexcel") ;
   }
   public static void exportToXML(String reportSource, String fileNameDestination  ,  Map parameters  ) throws JRException
   {
      EntityManager em = (EntityManager)Component.getInstance("entityManager") ;
      JRXmlExporter  exporter = new JRXmlExporter() ;
      exportToFormat(  reportSource, fileNameDestination  , parameters , em ,  exporter, "text/xml" ) ;
   }
   public static void exportToHTML(String reportSource, String fileNameDestination  ,  Map parameters  ) throws JRException
   {
      EntityManager em = (EntityManager)Component.getInstance("entityManager") ;
      JRHtmlExporter  exporter = new JRHtmlExporter() ;
      exportToFormat(  reportSource, fileNameDestination  , parameters , em ,  exporter , "text/html" ) ;
   }
   
   /**
    * 
    * @param reportSource : The source of the report template to use. The full path to the report can be given. If only the name is provided and the path is missing. Then the 
    * default report location will be used.
    * @param fileNameDestination
    * @param parameters
    * @param em : The EntityManager
    * @param exporterToUse 
    * @param contentType
    * @throws JRException
    */
   private static void exportToFormat(String reportSource, String fileNameDestination  ,  Map parameters , EntityManager em   , JRAbstractExporter exporterToUse , String contentType ) throws JRException
   {
      try
      {  
         FacesContext context = FacesContext.getCurrentInstance() ; 
         HttpServletResponse response = (HttpServletResponse) 
         context.getExternalContext().getResponse(); 

         Session session = (Session)em.getDelegate() ;
        
         response.setContentType(contentType);
         
         ReportExporterManager.getListOfJRXMLSubReportsAndCompileThem() ;
 
         if ( fileNameDestination == null ) fileNameDestination = ReportExporterManager.lastFileName(reportSource) ;        
         response.setHeader("Content-disposition", "attachment;filename=\"" + fileNameDestination + "\"");
          
         // Here we make sure that if the user provides the name of the report without any path, then we use the default path for the reports
         
         if ((ReportExporterManager.lastFileName(reportSource)).equals(reportSource)){
            reportSource = ApplicationPreferenceManager.getGazelleReportsPath(em)  + File.separatorChar + reportSource;
         }

         log.info("Report source is : "+ reportSource);
         JasperReport report = ReportRenderer.getJasperReport( reportSource ) ;
           
         parameters.put( JRParameter.REPORT_FILE_RESOLVER , new SimpleFileResolver( new File(ApplicationPreferenceManager.getGazelleReportsPath(em)  ) )) ;
         parameters.put("SUBREPORT_DIR", ApplicationPreferenceManager.getGazelleReportsPath(em) );
         
         Connection c = session.connection() ;
         
         JasperPrint jasperPrint=JasperFillManager.fillReport( report , parameters,   c );
          
      
          
        
         ServletOutputStream servletOutputStream;

         servletOutputStream = response.getOutputStream();

         exporterToUse.setParameter(JRExporterParameter.JASPER_PRINT,jasperPrint);
         exporterToUse.setParameter(JRExporterParameter.OUTPUT_STREAM, servletOutputStream );
         
         if ( exporterToUse instanceof JRHtmlExporter )
         {
            exporterToUse.setParameter(JRHtmlExporterParameter.IS_USING_IMAGES_TO_ALIGN , false);
            exporterToUse.setParameter(JRHtmlExporterParameter.IMAGES_URI,"image?image=");
         }
         exporterToUse.exportReport() ;
         
         
        
         servletOutputStream.flush(); 
         servletOutputStream.close();

       
         
         try{
            log.info("closing connection") ;
            
            c.close() ;
            log.info("connection closed") ;
         
         }
         catch (  SQLException e ){
            ExceptionLogging.logException(e, log);
            log.error("error :  SQLException" + e.getMessage()) ;
         }

         context.responseComplete() ;
      }
      catch (IOException e)
      {
         ExceptionLogging.logException(e, log);
      }
   }
   
   public static void getListOfJRXMLSubReportsAndCompileThem()
   {
      EntityManager em = (EntityManager) Component.getInstance("entityManager") ;
      File f = new File( ApplicationPreferenceManager.getGazelleReportsPath(em) ) ;
      log.info(ApplicationPreferenceManager.getGazelleReportsPath(em)) ;
      
      String[] filesToFilter = f.list() ;
      
          for ( String s : filesToFilter)
          {
             log.info(s) ;
             if ( s.indexOf(".jrxml") > -1  )
             {
                try
                {
               log.info(  " getJasperReport ->" + f.getAbsolutePath()+File.separatorChar+s.substring(0 , s.length() - ".jrxml".length() ) ) ;
                  ReportRenderer.getJasperReport( f.getAbsolutePath()+File.separatorChar+s.substring(0 , s.length() - ".jrxml".length() ) ) ;
                }
                catch (FileNotFoundException e)
                {
                   ExceptionLogging.logException(e, log);
                }
                catch (JRException e)
                {
                   ExceptionLogging.logException(e, log);
                }
             }
          }
      
   }
   
   /**
    * Destroy the Manager bean when the session is over.
    */
   @Destroy
   @Remove
   public void destroy()
   {

   }

 
}
