package eu.dnetlib.utils;

import java.util.Set;

import org.apache.commons.io.FilenameUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.dom4j.Document;
import org.dom4j.io.SAXReader;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.ResourceLoaderAware;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternUtils;
import org.springframework.stereotype.Component;

import eu.dnetlib.clients.is.DnetSchemaId;
import eu.dnetlib.exceptions.DnetGenericException;

@Component
public abstract class AbstractBulkResourceImporter implements ResourceLoaderAware {

	static final Log log = LogFactory.getLog(AbstractBulkResourceImporter.class);

	private static boolean initialized = false;

	private ResourceLoader resourceLoader;

	@Value("${bulk.importer.path:classpath*:/isStartupResources}")
	private String bootstrapPath;

	public void bulkImport() throws DnetGenericException {
		if (isInitialized()) { return; }

		final ResourcePatternResolver resolver = ResourcePatternUtils.getResourcePatternResolver(getResourceLoader());

		try {
			final long start = System.currentTimeMillis();

			final Set<DnetSchemaId> schemas = listAlreadyRegisterdSchemas();

			log.info("bulk import of profiles and schemas from " + bootstrapPath);
			for (final Resource res : resolver.getResources(bootstrapPath + "/**/*.xsd")) {
				final String filename = FilenameUtils.getBaseName(res.getFilename());
				if (StringUtils.countMatches(filename, "-") == 1) {
					final DnetSchemaId schemaId = new DnetSchemaId(StringUtils.substringBefore(filename, "-"), StringUtils.substringAfter(filename, "-"));
					if (!schemas.contains(schemaId)) {
						log.info(" - schema: " + schemaId);
						registerSchema(schemaId, IOUtils.toString(res.getInputStream()));
					}
				}
			}
			for (final Resource res : resolver.getResources(bootstrapPath + "/**/*.xml")) {
				final Document doc = new SAXReader().read(res.getInputStream());
				final String profId = doc.valueOf("//RESOURCE_IDENTIFIER/@value");
				if (!isProfileAlreadyRegistered(profId)) {
					log.info(" - profile: " + profId);
					registerProfile(IOUtils.toString(res.getInputStream()));
				}
			}
			log.info("bulk registration finished in: " + ((System.currentTimeMillis() - start) / 1000) + "s");
		} catch (final Exception e) {
			throw new DnetGenericException(e);
		} finally {
			setInitialized(true);
		}
	}

	protected abstract boolean isProfileAlreadyRegistered(String profId) throws Exception;

	protected abstract Set<DnetSchemaId> listAlreadyRegisterdSchemas() throws Exception;

	protected abstract void registerProfile(String profile) throws Exception;

	protected abstract void registerSchema(DnetSchemaId schemaId, String schema) throws Exception;

	public boolean isInitialized() {
		return initialized;
	}

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

	public ResourceLoader getResourceLoader() {
		return resourceLoader;
	}

	@Override
	public void setResourceLoader(final ResourceLoader resourceLoader) {
		this.resourceLoader = resourceLoader;
	}

}
