package net.ihe.common.report;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
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.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;

import net.ihe.gazelle.common.application.action.ApplicationPreferenceManager;
import net.ihe.gazelle.common.log.ExceptionLogging;
import net.ihe.gazelle.common.util.DocumentFileUpload;
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 org.hibernate.Session;
import org.jboss.seam.Component;
import org.jboss.seam.ScopeType;
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.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
	public 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 ;

	}

	/**
	 * not used on TM, perhaps it is used on Product-registry, otherwise delete it.
	 */
	@Deprecated
	public void exportToPDF_(String reportSource, String fileNameDestination  ,  Map<String, Object> parameters  ) throws JRException
	{
		if ( parameters == null ) parameters = new HashMap<String, Object >() ;
		ReportExporterManager.exportToPDF( reportSource , fileNameDestination , parameters  ) ;
	}

	/**
	 * not used on TM, perhaps it is used on Product-registry, otherwise delete it.
	 */
	@Deprecated
	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<String, Object> parameters  ) throws JRException
	{
		EntityManager em = (EntityManager)Component.getInstance("entityManager") ;
		JRPdfExporter exporter = new JRPdfExporter() ;
		String subreports = ApplicationPreferenceManager.instance().getGazelleReportsPath();
		exportToFormat(reportSource, subreports, fileNameDestination  , parameters , em ,  exporter , "application/pdf" ) ;
	}
	
	/**
	 * not used, verify if it is used on Product registry or delete it
	 * @param reportSource
	 * @param fileNameDestination
	 * @param parameters
	 * @throws JRException
	 */
	@Deprecated
	public static void exportToPDFAndSaveOnServer(String reportSource, String fileName, String fileNameDestination,  Map<String, Object> parameters  ) throws JRException {
		EntityManager em = (EntityManager)Component.getInstance("entityManager") ;
		ReportExporterManager.exportToPDFAndSaveOnServer(reportSource, fileName, fileNameDestination, parameters, em);
	}
	
	public static void exportToPDFAndSaveOnServer(String reportSource, String fileName, String fileNameDestination,  Map<String, Object> parameters , EntityManager em ) throws JRException
	{
		JRPdfExporter exporter = new JRPdfExporter() ;
		String subreports = ApplicationPreferenceManager.instance().getGazelleReportsPath();
		parameters.put( JRParameter.REPORT_FILE_RESOLVER , new SimpleFileResolver( new File(subreports) )) ;
		parameters.put("SUBREPORT_DIR", subreports + File.separatorChar );
		//exportToFormat(reportSource, subreports, fileName, parameters , em ,  exporter , "application/pdf" ) ;
		try {
			FileOutputStream fos = new FileOutputStream(new File(fileNameDestination));
			ReportExporterManager.exportToFormatForOutputStream(subreports, reportSource, 
					fileNameDestination, parameters, em, exporter, "application/pdf", fos);
			DocumentFileUpload.showFile(fileNameDestination, fileName, true);
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		}
		
	}

	/**
	 * not used on TM, perhaps it is used on Product-registry, otherwise delete it.
	 */
	@Deprecated
   public static void exportToUncompressedPDF(String reportSource, String fileNameDestination  ,  Map<String, Object> parameters  ) throws JRException
   {
      EntityManager em = (EntityManager)Component.getInstance("entityManager") ;
      JRPdfExporter exporter = new JRPdfExporter() ;
      exporter.setParameter(JRPdfExporterParameter.IS_COMPRESSED, false);
      String subreports = ApplicationPreferenceManager.instance().getGazelleReportsPath();
      exportToFormat( reportSource, subreports, fileNameDestination  , parameters , em ,  exporter , "application/pdf" ) ;
   }
	
	/**
	 * not used on TM, perhaps it is used on Product-registry, otherwise delete it.
	 */
	@Deprecated
	public static void exportToCSV(String reportSource, String fileNameDestination  ,  Map<String, Object> parameters  ) throws JRException
	{
		EntityManager em = (EntityManager)Component.getInstance("entityManager") ;
		JRCsvExporter  exporter = new JRCsvExporter() ;
		String subreports = ApplicationPreferenceManager.instance().getGazelleReportsPath();
		exportToFormat(reportSource, subreports, fileNameDestination  , parameters , em ,  exporter , "application/csv") ;
	}
	
	/**
	 * not used on TM, perhaps it is used on Product-registry, otherwise delete it.
	 */
	@Deprecated
	public static void exportToXLS(String reportSource, String fileNameDestination  ,  Map<String, Object> parameters  ) throws JRException
	{
		EntityManager em = (EntityManager)Component.getInstance("entityManager") ;
		JExcelApiExporter exporter = new JExcelApiExporter() ;
		String subreports = ApplicationPreferenceManager.instance().getGazelleReportsPath();
		exportToFormat(reportSource, subreports, fileNameDestination  , parameters , em ,  exporter , "application/msexcel") ;
	}
	
	/**
	 * not used on TM, perhaps it is used on Product-registry, otherwise delete it.
	 */
	@Deprecated
	public static void exportToXML(String reportSource, String fileNameDestination  ,  Map<String, Object> parameters  ) throws JRException
	{
		EntityManager em = (EntityManager)Component.getInstance("entityManager") ;
		JRXmlExporter  exporter = new JRXmlExporter() ;
		String subreports = ApplicationPreferenceManager.instance().getGazelleReportsPath();
		exportToFormat(reportSource, subreports, fileNameDestination  , parameters , em ,  exporter, "text/xml" ) ;
	}
	
	/**
	 * not used on TM, perhaps it is used on Product-registry, otherwise delete it.
	 */
	@Deprecated
	public static void exportToHTML(String reportSource, String fileNameDestination  ,  Map<String, Object> parameters  ) throws JRException
	{
		EntityManager em = (EntityManager)Component.getInstance("entityManager") ;
		JRHtmlExporter  exporter = new JRHtmlExporter() ;
		String subreports = ApplicationPreferenceManager.instance().getGazelleReportsPath();
		exportToFormat(reportSource, subreports, 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 subdirReports, String fileNameDestination,  
			Map<String, Object> parameters, EntityManager em, JRAbstractExporter exporterToUse , String contentType ) throws JRException
	{
		try
		{  
			parameters.put( JRParameter.REPORT_FILE_RESOLVER , new SimpleFileResolver( new File(subdirReports) )) ;
			parameters.put("SUBREPORT_DIR", subdirReports + File.separatorChar );
			
			FacesContext context = FacesContext.getCurrentInstance() ; 
			HttpServletResponse response = (HttpServletResponse) 
				context.getExternalContext().getResponse(); 

			response.setContentType(contentType);
			response.setHeader("Content-Disposition", "attachment;filename=\""+  fileNameDestination + "\"");

			ServletOutputStream servletOutputStream = response.getOutputStream();

			if ( exporterToUse instanceof JRHtmlExporter )
			{
				exporterToUse.setParameter(JRHtmlExporterParameter.IS_USING_IMAGES_TO_ALIGN , false);
				exporterToUse.setParameter(JRHtmlExporterParameter.IMAGES_URI,"image?image=");
			}

			ReportExporterManager.exportToFormatForOutputStream(subdirReports, reportSource, 
					fileNameDestination, parameters, em, exporterToUse, contentType, servletOutputStream);


			servletOutputStream.flush(); 
			servletOutputStream.close();

			context.responseComplete() ;
		}
		catch (IOException e)
		{
			ExceptionLogging.logException(e, log);
		}
	}
	
	public static void exportToFormatForOutputStream(String subdirReports, String reportSource, String fileNameDestination,  
			Map<String, Object> parameters, EntityManager em, JRAbstractExporter exporterToUse , String contentType,
			OutputStream outs) throws JRException, FileNotFoundException{
		
		Session session = (Session)em.getDelegate() ;

		ReportExporterManager.getListOfJRXMLSubReportsAndCompileThem(em, subdirReports) ;

		if ((ReportExporterManager.lastFileName(reportSource)).equals(reportSource)){
			reportSource = ApplicationPreferenceManager.instance().getGazelleReportsPath()  + 
				File.separatorChar + reportSource;
		}
		JasperReport report = ReportRenderer.getJasperReport( reportSource ) ;

		parameters.put( JRParameter.REPORT_LOCALE , java.util.Locale.ENGLISH) ;

		Connection c = session.connection() ;

		JasperPrint jasperPrint=JasperFillManager.fillReport( report , parameters,   c );


		exporterToUse.setParameter(JRExporterParameter.JASPER_PRINT,jasperPrint);
		exporterToUse.setParameter(JRExporterParameter.OUTPUT_STREAM, outs );

		if ( exporterToUse instanceof JRHtmlExporter )
		{
			exporterToUse.setParameter(JRHtmlExporterParameter.IS_USING_IMAGES_TO_ALIGN , false);
			exporterToUse.setParameter(JRHtmlExporterParameter.IMAGES_URI,"image?image=");
		}
		exporterToUse.exportReport() ;

		try{
			c.close() ;
			log.info("connection closed") ;

		}
		catch (  SQLException e ){
			ExceptionLogging.logException(e, log);
		}
	}

	
	

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

	


	/**
	 * 
	 */
	public static void exportToFile(String content, String fileNameDestination){
		ReportExporterManager.exportToFile(null, content, fileNameDestination);
	}
	
	public static void exportToFile(String contentType, String content, String fileNameDestination){
		if (content != null){
			ReportExporterManager.exportToFile(contentType, content.getBytes(), fileNameDestination);
		}
	}
	
	public static void exportToFile(String contentType, byte[] bytes, String fileNameDestination  ) 
	{
		try
		{  
			FacesContext context = FacesContext.getCurrentInstance() ; 
			HttpServletResponse response = (HttpServletResponse) 
			context.getExternalContext().getResponse(); 
			if (contentType != null){
				response.setContentType(contentType);
			}
			response.setHeader("Content-Disposition", "attachment;filename=" + fileNameDestination  );
			
			ServletOutputStream servletOutputStream;
			servletOutputStream = response.getOutputStream();
			servletOutputStream.write(bytes);
			servletOutputStream.flush(); 
			servletOutputStream.close();

			context.responseComplete() ;
		}
		catch (IOException e)
		{
			ExceptionLogging.logException(e, log);
		}
	}
	
	/**
	 * used by product registry
	 */
	@Deprecated
	public static void getListOfJRXMLSubReportsAndCompileThem(){
		EntityManager em = (EntityManager)Component.getInstance("entityManager");
		getListOfJRXMLSubReportsAndCompileThem(em);
	}
	
	public static void getListOfJRXMLSubReportsAndCompileThem(EntityManager em){
		String reportsPath = ApplicationPreferenceManager.instance().getGazelleReportsPath();
		getListOfJRXMLSubReportsAndCompileThem(em, reportsPath);
	}
	
	public static void getListOfJRXMLSubReportsAndCompileThem(EntityManager em, String reportsPath)
	{
		File f = new File(reportsPath);
		log.info(reportsPath) ;

		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()
	{

	}


}
