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.Stateless;
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.JRPdfExporterParameter;
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;


@Stateless
@Scope(ScopeType.APPLICATION)
@Name("reportExporterManagerBean")
public class ReportExporterManager implements Serializable, ReportExporterManagerLocal
{
	
	/** Serial ID version of this object */
	private static final long serialVersionUID = 1405721611038200962L;

	/** 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" ) ;
	}
	
	/**
	 * 
	 * @param reportSource
	 * @param fileNameDestination
	 * @param parameters
	 * @throws JRException
	 */
	public static void exportToPDFAndSaveOnServer(String reportSource, String fileName, String fileNameDestination,  Map parameters  ) throws JRException
	{
		EntityManager em = (EntityManager)Component.getInstance("entityManager") ;
		JRPdfExporter exporter = new JRPdfExporter() ;
		exportToFormat(  reportSource, fileName, parameters , em ,  exporter , "application/pdf" ) ;
		
		// Do the save file action 
		// TODO 
		/*
		Map<String,Object> params = new HashMap<String,Object>();  
		Connection connection = ((Session) em.getDelegate() ).connection() ;
		try {
		File gazelleDataReports  = new File(ApplicationPreferenceManager.getGazelleReportsPath()) ;
		log.info("report = " +  gazelleDataReports.getAbsolutePath()+ File.separatorChar + reportSource);
		//log.info("reportJrxml = " +reportJrxml);
		JasperReport report = ReportRenderer.getJasperReport(gazelleDataReports.getAbsolutePath()+ File.separatorChar + reportSource) ;
		JasperPrint jasperPrint=JasperFillManager.fillReport( report , parameters,   connection );
		exporter.setParameter(JRExporterParameter.JASPER_PRINT,jasperPrint);			
		exporter.setParameter(JRExporterParameter.OUTPUT_FILE_NAME, fileNameDestination ) ;
		exporter.exportReport() ;
		log.info("fileNameDestination = " +fileNameDestination);
		connection.close() ;
		} catch (Exception e)
		{
			log.error("Exception = " + e.getMessage());
			return;
		}
		log.info("Exported !");
		 */
	}

   public static void exportToUncompressedPDF(String reportSource, String fileNameDestination  ,  Map parameters  ) throws JRException
   {
      EntityManager em = (EntityManager)Component.getInstance("entityManager") ;
      JRPdfExporter exporter = new JRPdfExporter() ;
      exporter.setParameter(JRPdfExporterParameter.IS_COMPRESSED, false);
      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
	 */
	@SuppressWarnings({ "deprecation", "unchecked" })
	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()  + 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()  ) )) ;
			parameters.put("SUBREPORT_DIR", ApplicationPreferenceManager.getGazelleReportsPath() + File.separatorChar );
			parameters.put( JRParameter.REPORT_LOCALE , java.util.Locale.ENGLISH) ;

			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);
		}
	}

	
	

	/**
	 * 
	 */
	@SuppressWarnings({ "deprecation", "unchecked" })
	public static void exportToTxt(String content, String fileNameDestination  ) 
	{
		try
		{  
			FacesContext context = FacesContext.getCurrentInstance() ; 
			HttpServletResponse response = (HttpServletResponse) 
			context.getExternalContext().getResponse(); 
			response.setContentType("text/plain");

			
			//if ( fileNameDestination == null ) fileNameDestination = ReportExporterManager.lastFileName(reportSource) ;        
			response.setHeader("Content-Disposition", "attachment;filename=" + fileNameDestination  );
			
			ServletOutputStream servletOutputStream;
			servletOutputStream = response.getOutputStream();
			servletOutputStream.write( content.getBytes());
			servletOutputStream.flush(); 
			servletOutputStream.close();

			context.responseComplete() ;
		}
		catch (IOException e)
		{
			ExceptionLogging.logException(e, log);
		}
	}

	


	/**
	 * 
	 */
	@SuppressWarnings({ "deprecation", "unchecked" })
	public static void exportToFile(String content, String fileNameDestination  ) 
	{
		try
		{  
			FacesContext context = FacesContext.getCurrentInstance() ; 
			HttpServletResponse response = (HttpServletResponse) 
			context.getExternalContext().getResponse(); 
			//response.setContentType("text/plain");

			
			//if ( fileNameDestination == null ) fileNameDestination = ReportExporterManager.lastFileName(reportSource) ;        
			response.setHeader("Content-Disposition", "attachment;filename=" + fileNameDestination  );
			
			ServletOutputStream servletOutputStream;
			servletOutputStream = response.getOutputStream();
			servletOutputStream.write( content.getBytes());
			servletOutputStream.flush(); 
			servletOutputStream.close();

			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() ) ;
		log.info(ApplicationPreferenceManager.getGazelleReportsPath()) ;

		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.
	 */
	@Remove
	public void destroy()
	{

	}


}
