package com.jware.apps.scheduler.init;

import java.beans.IntrospectionException;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.Collection;
import java.util.Iterator;
import java.util.Map;

import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.betwixt.io.BeanReader;
import org.quartz.Scheduler;
import org.quartz.impl.StdSchedulerFactory;
import org.xml.sax.SAXException;

import com.jware.apps.scheduler.model.DefinitionManager;
import com.jware.apps.scheduler.model.JobDefinition;
import com.jware.apps.scheduler.util.JobSchedulerUtils;

/**
 * @author Jrmt
 */

public class DefinitionInitializer extends HttpServlet {

	public static String DEFAULT_DEFINITION_FILE = "/JobDefinitions.xml";
	public static final String PROPERTIES_FILE = "org.quartz.properties";
    private boolean performShutdown = true;
    
	public void init(ServletConfig cfg) throws ServletException {

		super.init(cfg);

		ServletContext context = cfg.getServletContext();
		String configFile = null;
		String quartz_properties = this.getInitParameter("quartz-properties");
		if (quartz_properties != null)
		{
			System.setProperty(PROPERTIES_FILE, context.getRealPath(quartz_properties));
			configFile = context.getRealPath(quartz_properties);
		} else {
			configFile = cfg.getInitParameter("config-file");
		}
        String shutdownPref = cfg.getInitParameter("shutdown-on-unload");
        
        if(shutdownPref != null)
            performShutdown = Boolean.getBoolean(shutdownPref);

		log("Quartz Initializer Servlet loaded, initializing Scheduler...");

        StdSchedulerFactory factory;
        try {

            // get Properties
            if (configFile != null)
            {
                factory = new StdSchedulerFactory(configFile);
            }
            else
            {
                factory = new StdSchedulerFactory();
            }
    
            Scheduler scheduler = factory.getScheduler();
            scheduler.start();
    
          } catch (Exception e) {
              log("Quartz Scheduler failed to initialize: " + e.toString());
              throw new ServletException(e);
          }
		
		String definitionPath = this.getInitParameter("definition-file");

		if (definitionPath == null)
			definitionPath = "/WEB-INF/JobDefinitions.xml";

		BeanReader beanReader = new BeanReader();

		// Configure the reader
		beanReader.getXMLIntrospector().setAttributesForPrimitives(false);

		if (definitionPath != null && definitionPath != "") {
			// Now we parse the xml
			try {
				// Register beans so that betwixt knows what the xml is to be converted to

				beanReader.registerBeanClass("JobDefinitions", DefinitionManager.class);
				File defFile = new File(context.getRealPath(definitionPath));

				if (!defFile.exists()) {

					log("Alternate user definitions file, not specfic or does not exist.  Default resource /JobDefinitions.xml will be tried.");

					//defFile = new File(context.getRealPath("/WEB-INF/JobDefinitions.xml"));
					log(
						"Attempting to read definitions from file "
							+ this.getClass().getResource(DEFAULT_DEFINITION_FILE).getFile());

					URL url = this.getClass().getResource(DEFAULT_DEFINITION_FILE);

					if (url == null) {
						log("resource " + DEFAULT_DEFINITION_FILE + " not found");
					}

					defFile = new File(url.getFile());

				} else {
					log("Reading definitions from " + definitionPath);
				}

				DefinitionManager defs = (DefinitionManager) beanReader.parse(defFile);

				if (defs != null) {
					
					context.setAttribute(JobSchedulerUtils.JOB_DEFINITIONS_PROP, defs);
					log(defs.getDefinitions().size() + " Definition(s) loaded from config file");
					
					Map map = defs.getDefinitions();
					Collection values = map.values();
					
					for(Iterator iterator=values.iterator(); iterator.hasNext();){
						JobDefinition jobDef = (JobDefinition)iterator.next();

						log("Job Name = " + jobDef.getName() );
						
					}
					
				} else {
					log("no definitions found");

				}

			} catch (IntrospectionException e) {
			} catch (IOException e) {
				e.printStackTrace();
				//To change body of catch statement use Options | File Templates.
			} catch (SAXException e) {
				e.printStackTrace();
				//To change body of catch statement use Options | File Templates.
			}
		} else {

			log("Error definition-file init parameter not specified");

		}

	}

	public void destroy() {
	    
        if(!performShutdown)
            return;
	    try {
	        Collection scheduleCollection = new StdSchedulerFactory().getAllSchedulers();
	        Iterator itr = scheduleCollection.iterator();
            while (itr.hasNext()) {
                Scheduler scheduler = (Scheduler) itr.next();
                scheduler.shutdown();
            }
	    } catch( Exception e ) {
	        e.printStackTrace();
	    }
	    this.getServletContext().setAttribute(JobSchedulerUtils.JOB_DEFINITIONS_PROP, null);
		super.destroy();

	}

    public void doPost(HttpServletRequest request, HttpServletResponse response)
    	throws ServletException, IOException {
    		response.sendError(HttpServletResponse.SC_FORBIDDEN);
    }

    public void doGet(HttpServletRequest request, HttpServletResponse response)
    	throws ServletException, IOException {
    		response.sendError(HttpServletResponse.SC_FORBIDDEN);
    }
}