package eu.dnetlib.enabling.is.store;

import java.io.IOException;

import javax.xml.parsers.ParserConfigurationException;
import javax.xml.xpath.XPathExpressionException;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.springframework.beans.factory.annotation.Required;
import org.springframework.core.io.Resource;
import org.xml.sax.SAXException;

import eu.dnetlib.enabling.is.registry.rmi.ISRegistryException;
import eu.dnetlib.enabling.tools.ResourceLoaderHelper;
import eu.dnetlib.miscutils.coupling.StaticCondition;

/**
 * This job is scheduled at startup of a test environment to load some data into the store.
 * 
 * <p>
 * You should configure this bean with paths to the profile and schema files you want to add. This can be done setting
 * the 'resources' and 'schemas' properties using the syntax documented <a
 * href="http://static.springframework.org/spring/docs/
 * 2.5.x/reference/resources.html#resources-app-ctx-wildcards-in-resource-paths">here</a>
 * </p>
 * 
 * @author marko
 * 
 */
public class TestContentInitializerJob extends AbstractContentInitializer implements Job {
	/**
	 * milliseconds in a second.
	 */
	private static final double MILLIS = 1000.0;

	/**
	 * logger.
	 */
	static final Log log = LogFactory.getLog(TestContentInitializerJob.class); // NOPMD by marko on 11/24/08 5:02 PM

	/**
	 * hackish way of communicating to the integration tester that we have finished.
	 */
	private static boolean initialized = false;
	
	/**
	 * resourceLoader compatible pattern matching all files to load.
	 */
	private String resources;

	/**
	 * resourceLoader compatible pattern matching all xsd files to load.
	 */
	private String schemas;

	/**
	 * resource loader helper. we cannot implement the ResourceLoaderAware interface.
	 */
	private ResourceLoaderHelper resourceLoader;

	/**
	 * set to true in order to disable notification detection. Useful for bulk profile insertion.
	 */
	private StaticCondition snDisable;

	public TestContentInitializerJob() {
		super();
	}

	/**
	 * {@inheritDoc}
	 * 
	 * @see org.quartz.Job#execute(org.quartz.JobExecutionContext)
	 */
	@Override
	public void execute(final JobExecutionContext arg0) throws JobExecutionException {
		initialize();
		setInitialized(true);
	}

	public void initialize() throws JobExecutionException {
		log.info("Initializing store with some profiles and collections for test and development ...");

		if (!getBulkImporter().isEnabled()) {
			log.info("skipping store initialization because the database already exists");
			return;
		}

		log.info("loading resources: " + getResources());

		try {
			String type = "schema/profile"; // NOPMD
			String name = "none"; // NOPMD
			try {
				final long start = System.currentTimeMillis();

				type = "schema"; // NOPMD
				for (Resource res : resourceLoader.getResourcePatternResolver().getResources(schemas)) {
					name = res.getURL().toString(); // NOPMD
					registerSchema(res.getURL());
				}

				try {
					snDisable.setCondition(true);
					type = "profile";
					for (Resource res : resourceLoader.getResourcePatternResolver().getResources(resources)) {
						name = res.getURL().toString(); // NOPMD
						registerProfile(res.getURL());
					}
				} finally {
					snDisable.setCondition(false);
				}

				log.info("bulk registration finished in: " + ((System.currentTimeMillis() - start) / MILLIS) + "s");
			} catch (ISRegistryException e) {
				log.fatal("cannot register " + type + ": " + name, e);
				throw new JobExecutionException("registry exception", e);
			} catch (IOException e) {
				throw new JobExecutionException("io exception", e);
			} catch (XPathExpressionException e) {
				throw new JobExecutionException("xpath exception", e);
			} catch (SAXException e) {
				throw new JobExecutionException("sax exception", e);
			} catch (ParserConfigurationException e) {
				throw new JobExecutionException("parser exception", e);
			}
		} finally {
			log.info("INITIALIZED");
			setInitialized(true);
		}
	}

	public static void setInitialized(final boolean initialized) {
		TestContentInitializerJob.initialized = initialized;
	}

	public static boolean isInitialized() {
		return initialized;
	}

	public void setResources(final String resources) {
		this.resources = resources;
	}

	public String getResources() {
		return resources;
	}

	@Required
	public ResourceLoaderHelper getResourceLoader() {
		return resourceLoader;
	}

	@Required
	public void setResourceLoader(final ResourceLoaderHelper resourceLoader) {
		this.resourceLoader = resourceLoader;
	}

	@Required
	public void setSchemas(final String schemas) {
		this.schemas = schemas;
	}

	public String getSchemas() {
		return schemas;
	}

	public void setSnDisable(final StaticCondition snDisable) {
		this.snDisable = snDisable;
	}

	public StaticCondition getSnDisable() {
		return snDisable;
	}

}
