package eu.dnetlib.enabling.manager.msro;

import org.antlr.stringtemplate.StringTemplate;
import org.springframework.beans.factory.annotation.Required;

import eu.dnetlib.enabling.is.lookup.rmi.ISLookUpDocumentNotFoundException;
import eu.dnetlib.enabling.is.lookup.rmi.ISLookUpException;
import eu.dnetlib.enabling.is.lookup.rmi.ISLookUpService;
import eu.dnetlib.enabling.is.registry.rmi.ISRegistryException;
import eu.dnetlib.enabling.is.registry.rmi.ISRegistryService;
import eu.dnetlib.enabling.tools.ServiceLocator;

/**
 * Persistent manager map maintained in the IS.
 *
 * @author marko
 *
 */
public class ISManagerMapImpl implements ManagerMap {

	/**
	 * lookup locator.
	 */
	private ServiceLocator<ISLookUpService> lookUpLocator;

	/**
	 * registry locator.
	 */
	private ServiceLocator<ISRegistryService> registryLocator;

	/**
	 * empty map template.
	 */
	private StringTemplate emptyMapTemplate;

	/**
	 * {@inheritDoc}
	 *
	 * @see eu.dnetlib.enabling.manager.msro.ManagerMap#indexForMDStore(java.lang.String)
	 */
	public String indexForMDStore(final String mdId) {
		try {
			ensureMapExists();
			final String query = "collection('/db/DRIVER/ManagerServiceMapDSResources/ManagerServiceMapDSResourceType')//INDEX_MAP/INDEX[MDSTORE/@id='"
					+ mdId + "']/@id/string()";

			return lookUpLocator.getService().getResourceProfileByQuery(query);

		} catch (final ISLookUpDocumentNotFoundException e) {
			return null;
		} catch (final ISLookUpException e) {
			throw new IllegalStateException(e);
		} catch (final ISRegistryException e) {
			throw new IllegalStateException(e);
		}
	}

	/**
	 * {@inheritDoc}
	 *
	 * @see eu.dnetlib.enabling.manager.msro.ManagerMap#registerIndexForMDStore(java.lang.String, java.lang.String)
	 */
	public void registerIndexForMDStore(final String mdId, final String indexId) {
		try {
			ensureMapExists();

			final String xupdate = "for $x in collection('/db/DRIVER/ManagerServiceMapDSResources/ManagerServiceMapDSResourceType')//INDEX_MAP "
					+ "return update insert <INDEX format=\"DMF\" parentId=\"\" hiId=\"\" id=\"" + indexId + "\">" + "<MDSTORE parentId=\"\" id=\""
					+ mdId + "\"/>" + "</INDEX> into $x";
			registryLocator.getService().executeXUpdate(xupdate);

		} catch (final ISLookUpException e) {
			throw new IllegalStateException(e);
		} catch (final ISRegistryException e) {
			throw new IllegalStateException(e);
		}
	}

	/**
	 * {@inheritDoc}
	 *
	 * @see eu.dnetlib.enabling.manager.msro.ManagerMap#removeIndex(java.lang.String)
	 */
	public void removeIndex(final String indexId) {
		try {
			final String xupdate = "for $x in collection('/db/DRIVER/ManagerServiceMapDSResources/ManagerServiceMapDSResourceType')//INDEX_MAP "
					+ "return update delete $x//INDEX[@id = '" + indexId + "']";

			registryLocator.getService().executeXUpdate(xupdate);
		} catch (final ISRegistryException e) {
			throw new IllegalStateException(e);
		}
	}

	/**
	 * {@inheritDoc}
	 *
	 * @see eu.dnetlib.enabling.manager.msro.ManagerMap#removeMDStore(java.lang.String)
	 */
	public void removeMDStore(final String mdId) {
		try {
			final String xupdate = "for $x in collection('/db/DRIVER/ManagerServiceMapDSResources/ManagerServiceMapDSResourceType')//INDEX_MAP "
					+ "return update delete $x//INDEX[MDSTORE[@id = '" + mdId + "']]";

			registryLocator.getService().executeXUpdate(xupdate);
		} catch (final ISRegistryException e) {
			throw new IllegalStateException(e);
		}
	}

	/**
	 * ensure that the manager map exists.
	 *
	 * @throws ISLookUpException
	 *             could happen
	 * @throws ISRegistryException
	 *             could happen
	 */
	private void ensureMapExists() throws ISLookUpException, ISRegistryException {
		try {
			lookUpLocator.getService().getResourceProfileByQuery("collection('/db/DRIVER/ManagerServiceMapDSResources/ManagerServiceMapDSResourceType')");
		} catch (final ISLookUpDocumentNotFoundException e) {
			registryLocator.getService().registerProfile(emptyMapTemplate.toString());
		}
	}

	public ServiceLocator<ISLookUpService> getLookUpLocator() {
		return lookUpLocator;
	}

	@Required
	public void setLookUpLocator(final ServiceLocator<ISLookUpService> lookUpLocator) {
		this.lookUpLocator = lookUpLocator;
	}

	public ServiceLocator<ISRegistryService> getRegistryLocator() {
		return registryLocator;
	}

	@Required
	public void setRegistryLocator(final ServiceLocator<ISRegistryService> registryLocator) {
		this.registryLocator = registryLocator;
	}

	public StringTemplate getEmptyMapTemplate() {
		return emptyMapTemplate;
	}

	@Required
	public void setEmptyMapTemplate(final StringTemplate emptyMapTemplate) {
		this.emptyMapTemplate = emptyMapTemplate;
	}

}
