package eu.dnetlib.actionmanager.is;

import java.util.List;

import javax.xml.ws.Endpoint;

import org.antlr.stringtemplate.StringTemplate;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Required;

import com.google.common.base.Function;
import com.google.common.base.Splitter;
import com.google.common.collect.Lists;

import eu.dnetlib.actionmanager.rmi.ActionManagerException;
import eu.dnetlib.actionmanager.set.ActionManagerSet;
import eu.dnetlib.actionmanager.set.ActionManagerSet.ImpactTypes;
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;
import eu.dnetlib.soap.EndpointReferenceBuilder;

public class ISClient {

	private ServiceLocator<ISRegistryService> registryLocator;
	private ServiceLocator<ISLookUpService> lookupLocator;
	/**
	 * Template for ActionManagerSet profiles
	 */
	private StringTemplate actionManagerSetDsTemplate;

	/**
	 * service endpoint.
	 */
	private Endpoint endpoint;

	/**
	 * endpoint builder.
	 */
	private EndpointReferenceBuilder<Endpoint> eprBuilder;

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

	public String registerSetProfile(ActionManagerSet set) throws ActionManagerException {
		if (existsSet(set.getId())) {
			throw new ActionManagerException("Set " + set.getId() + " already registered");
		}
		try {
			StringTemplate template = new StringTemplate(actionManagerSetDsTemplate.getTemplate());
			template.setAttribute("serviceUri", eprBuilder.getAddress(endpoint));
			template.setAttribute("set", set);
			return registryLocator.getService().registerProfile(template.toString());
		} catch (ISRegistryException e) {
			throw new ActionManagerException("Error registering set " + set, e);
		}
	}

	public List<ActionManagerSet> listSets() {
		String q = "for $x in collection('/db/DRIVER/ActionManagerSetDSResources/ActionManagerSetDSResourceType') "
				+ "return concat(' ', $x//SET/@id, ' @@@ ', $x//SET/text(), ' @@@ ', $x//IMPACT, ' @@@ ', $x//LAST_EXECUTION_DATE, ' ')";

		try {
			return Lists.newArrayList(Lists.transform(lookupLocator.getService().quickSearchProfile(q), new Function<String, ActionManagerSet>() {
				@Override
				public ActionManagerSet apply(String s) {
					List<String> list = Lists.newArrayList(Splitter.on("@@@").split(s));
					return new ActionManagerSet(list.get(0).trim(), list.get(1).trim(), ImpactTypes.valueOf(list.get(2).trim()), list.get(3).trim());
				}
			}));
		} catch (ISLookUpException e) {
			log.error("Error accessing Sets");
			return Lists.newArrayList();
		}

	}

	public boolean existsSet(String id) {
		String q = "for $x in collection('/db/DRIVER/ActionManagerSetDSResources/ActionManagerSetDSResourceType') where $x//SET/@id = '" + id
				+ "' return $x";
		try {
			return !lookupLocator.getService().quickSearchProfile(q).isEmpty();
		} catch (ISLookUpException e) {
			log.error("Error accessing Sets");
			return false;
		}
	}

	public StringTemplate getActionManagerSetDsTemplate() {
		return actionManagerSetDsTemplate;
	}

	@Required
	public void setActionManagerSetDsTemplate(StringTemplate actionManagerSetDsTemplate) {
		this.actionManagerSetDsTemplate = actionManagerSetDsTemplate;
	}

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

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

	public Endpoint getEndpoint() {
		return endpoint;
	}

	@Required
	public void setEndpoint(Endpoint endpoint) {
		this.endpoint = endpoint;
	}

	public EndpointReferenceBuilder<Endpoint> getEprBuilder() {
		return eprBuilder;
	}

	@Required
	public void setEprBuilder(EndpointReferenceBuilder<Endpoint> eprBuilder) {
		this.eprBuilder = eprBuilder;
	}

	public ServiceLocator<ISLookUpService> getLookupLocator() {
		return lookupLocator;
	}

	@Required
	public void setLookupLocator(ServiceLocator<ISLookUpService> lookupLocator) {
		this.lookupLocator = lookupLocator;
	}

}
