package an.xacml.adapter.file;

import javax.xml.ws.wsaddressing.W3CEndpointReference;

import org.apache.log4j.Logger;

import an.xacml.PolicySyntaxException;
import an.xacml.adapter.DataAdapterException;
import an.xacml.engine.BuiltInFunctionNotFoundException;
import an.xacml.engine.CacheSizeExceedCapacityException;
import an.xacml.engine.PDP;
import eu.dnetlib.common.ws.epr.W3CEPRUtils;
import eu.dnetlib.common.ws.nh.NotificationConstants;
import eu.dnetlib.common.ws.nh.deleg.INotificationDelegatorClient;
import eu.dnetlib.enabling.aas.ws.nh.AASNotificationConstants;
import eu.dnetlib.enabling.aas.ws.nh.NotificationUtils;
import eu.dnetlib.enabling.is.sn.rmi.ISSNException;
import eu.dnetlib.enabling.is.sn.rmi.ISSNService;
import eu.dnetlib.enabling.tools.ServiceLocator;

/**
 * ISLookupDataStore notification handler.
 * @author mhorst
 *
 */
public class ISLookupDataStoreNotificationHandler implements INotificationDelegatorClient {

	
	protected final Logger log = Logger.getLogger(this.getClass());
	
	/**
     * used by NotificationDelegator to pick supported notification consumer.
     */
    public static final String TOPIC_REGEX_PATTERN = "("+NotificationConstants.TOPIC_PREFIX_CREATE+"\\.|"+
            NotificationConstants.TOPIC_PREFIX_DELETE+"\\.|"+
            NotificationConstants.TOPIC_PREFIX_UPDATE+"\\.)"+
            AASNotificationConstants.SEC_POLICY_RESOURCE_TYPE +
            ".*";

    /**
	 * Notification consumer reference URL.
	 */
	private String consumerReferenceURL;
	
	/**
	 * Notification consumer reference WSDL location.
	 */
	private String consumerReferenceWSDL;
	
	/**
	 * Notification consumer reference EPR generated at service startup.
	 */
	private W3CEndpointReference generatedConsumerReferenceEPR;
	
	/**
	 * {@link ISSNService} locator.
	 */
	private ServiceLocator<ISSNService> issnLocator;
	
	/**
	 * Related {@link PDP} instance required to trigger reloading policies.
	 */
	private PDP pdp;

	/**
	 * Subscribes to receiving policies related notifications.
	 * @throws ISSNException 
	 */
	public void init() throws ISSNException {
//		initializing local EPR
		this.generatedConsumerReferenceEPR = (consumerReferenceWSDL!=null)?
				W3CEPRUtils.buildEPR(consumerReferenceURL, consumerReferenceWSDL):
					W3CEPRUtils.buildEPR(consumerReferenceURL);
//		subscribing to policies changes
		String[] subscrModes = new String[] {
				NotificationConstants.TOPIC_PREFIX_CREATE,
				NotificationConstants.TOPIC_PREFIX_DELETE,
				NotificationConstants.TOPIC_PREFIX_UPDATE
		};
		for (String subscrMode : subscrModes) {
			String subscrId = issnLocator.getService().subscribe(
					generatedConsumerReferenceEPR, 
					NotificationUtils.buildTopic(subscrMode, 
							AASNotificationConstants.SEC_POLICY_RESOURCE_TYPE), 
					NotificationConstants.TERMINATION_TIME_INFINITE);
			log.info("subscribed to " + subscrMode +
					" topic for resource type: " + AASNotificationConstants.SEC_POLICY_RESOURCE_TYPE + 
					" with subscrId: " + subscrId);
		}
	}

	/* (non-Javadoc)
	 * @see eu.dnetlib.enabling.aas.ws.nh.deleg.INotificationDelegatorClient#getTopicRegexPattern()
	 */
	@Override
	public String getTopicRegexPattern() {
		return TOPIC_REGEX_PATTERN;
	}

	/* (non-Javadoc)
	 * @see eu.dnetlib.enabling.aas.ws.nh.INotificationHandler#notify(java.lang.String, java.lang.String, java.lang.String, java.lang.String)
	 */
	@Override
	public boolean notify(String subscrId, String topic, String isId,
			String message) {
//		FIXME PolicyCache#update() method is not implemented therefore simply reloading all policies
//		we cannot simply add policy either, it is adviced in CacheManager#addPolicies() comment to 
//		use PolicyCache#update() method which is empty...
		log.debug("got policy related notification, simply reloading all policies...");
		try {
			pdp.reloadPolicies();
			return true;
		} catch (DataAdapterException e) {
			log.error("reloading policies failed!", e);
			return false;
		} catch (CacheSizeExceedCapacityException e) {
			log.error("reloading policies failed!", e);
			return false;
		} catch (PolicySyntaxException e) {
			log.error("reloading policies failed!", e);
			return false;
		} catch (BuiltInFunctionNotFoundException e) {
			log.error("reloading policies failed!", e);
			return false;
		}
	}

	/**
	 * Sets {@link ISSNService} locator.
	 * @param issnLocator
	 */
	public void setIssnLocator(ServiceLocator<ISSNService> issnLocator) {
		this.issnLocator = issnLocator;
	}

	/**
	 * Sets related {@link PDP} instance.
	 * @param pdp
	 */
	public void setPdp(PDP pdp) {
		this.pdp = pdp;
	}
	
	/**
	 * Sets consumerReferenceURL.
	 * @param consumerReferenceURL
	 */
	public void setConsumerReferenceURL(String consumerReferenceURL) {
		this.consumerReferenceURL = consumerReferenceURL;
	}

	/**
	 * Sets consumerReferenceWSDL.
	 * @param consumerReferenceWSDL
	 */
	public void setConsumerReferenceWSDL(String consumerReferenceWSDL) {
		this.consumerReferenceWSDL = consumerReferenceWSDL;
	}
}
