package eu.dnetlib.common.ws;

import javax.xml.ws.wsaddressing.W3CEndpointReference;

import org.apache.log4j.Logger;

import eu.dnetlib.enabling.aas.is.ISUtils;
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.sn.rmi.ISSNService;
import eu.dnetlib.enabling.tools.OpaqueResource;
import eu.dnetlib.enabling.tools.ServiceLocator;
import eu.dnetlib.enabling.tools.StringOpaqueResource;
import eu.dnetlib.enabling.tools.registration.ServiceRegistrator;


/**
 * Simple job registering service in IS.
 * To be invoked by org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean.
 * @author mhorst
 *
 */
public class RegisterServiceSimpleJob {

	protected static final Logger log = Logger.getLogger(RegisterServiceSimpleJob.class);

	/**
	 * Address of the service to be registered.
	 */
	private String serviceAddress;
	
	/**
	 * Address of the service WSDL.
	 * Optional parameter, if not provided '?wsdl' suffix will be added to serviceAddress parameter.
	 */
	private String serviceWSDL;
	
	/**
	 * Service name of the service to be registered.
	 * Part of resource type name. 
	 */
	private String serviceName;

	/**
	 * ISLookUp service locator.
	 */
	private ServiceLocator<ISLookUpService> lookUpServiceLocator;
	
	/**
	 * ISSN service locator.
	 */
	private ServiceLocator<ISSNService> snServiceLocator;

	/**
	 * Service registrator.
	 */
	private ServiceRegistrator serviceRegistrator;
	
	/**
	 * Blackboard registration flag.
	 */
	private boolean blackboardRegistration = false;

	/**
	 * Generated consumer reference.
	 */
	private W3CEndpointReference generatedConsumerReferenceEPR;

	/**
	 * Init method.
	 */
	public void init() {
//		initializing local EPR
		this.generatedConsumerReferenceEPR = (serviceWSDL!=null)?
				ISUtils.buildEPR(serviceAddress, serviceWSDL):ISUtils.buildEPR(serviceAddress);
	}
	
	public void register() {
		String profile = null;
		try {
			try {
				String xQuery = "collection('/db/DRIVER/ServiceResources')//RESOURCE_PROFILE/HEADER"
						+ "[RESOURCE_TYPE[@value='"
						+ serviceName + "ResourceType']]"
						+ "[PROTOCOLS/PROTOCOL[@address='"
						+ serviceAddress + "']]" + "/RESOURCE_IDENTIFIER[@value]";

				log.info("Veryfing if service is registered in IS...");
				profile = lookUpServiceLocator.getService().getResourceProfileByQuery(xQuery);

			} catch (ISLookUpDocumentNotFoundException e) {
					log.debug("Service is not existing in IS Registry");
			} catch (ISLookUpException e) {
					String message = "Failed to verify service profile in ISLookUp";
					log.error(message, e);
					return;
			}

			if (profile == null) {
				log.info("Registering Service in IS...");
				String profId = serviceRegistrator.registerService(serviceName,
						generatedConsumerReferenceEPR);
				if (profId==null) {
					log.error("Service registration failed: got null profId!");
					return;
				}
				log.debug("Validating service profile: " + profId);
				String validprofId = serviceRegistrator.validateProfile(profId);
				log.debug("Service profile validated: " + validprofId);

				if (blackboardRegistration) {
					log.debug("Subscribing service to the BLACKBOARD/LAST_REQUEST element "
									+ "in order to receive messages for the orchestration protocol");
					final OpaqueResource serviceProfile = new StringOpaqueResource(
							lookUpServiceLocator.getService().getResourceProfile(validprofId));
					snServiceLocator.getService().subscribe(generatedConsumerReferenceEPR, "UPDATE/"
							+ serviceProfile.getResourceType() + "/"
							+ validprofId
							+ "/RESOURCE_PROFILE/BODY/BLACKBOARD/LAST_REQUEST",
							0);
					log.debug("Subscribtion successful");
				}
				log.info("Service registration successful.");
			} else {
				String message = "This Service is already registered in IS: "
						+ profile;
				log.info(message);
			}
		} catch (Exception e) {
			String message = "Failed to register service in Information Service";
			log.error(message, e);
		}
	}

	public void setServiceAddress(String serviceAddress) {
		this.serviceAddress = serviceAddress;
	}

	public void setServiceWSDL(String serviceWSDL) {
		this.serviceWSDL = serviceWSDL;
	}

	public void setServiceName(String serviceName) {
		this.serviceName = serviceName;
	}

	public void setServiceRegistrator(ServiceRegistrator serviceRegistrator) {
		this.serviceRegistrator = serviceRegistrator;
	}

	public void setBlackboardRegistration(boolean blackboardRegistration) {
		this.blackboardRegistration = blackboardRegistration;
	}
	
	public void setLookUpServiceLocator(
			ServiceLocator<ISLookUpService> lookUpServiceLocator) {
		this.lookUpServiceLocator = lookUpServiceLocator;
	}

	public void setSnServiceLocator(ServiceLocator<ISSNService> snServiceLocator) {
		this.snServiceLocator = snServiceLocator;
	}
}
