package eu.dnetlib.enabling.is.sn.resourcestate;

import java.io.StringReader;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
import javax.xml.transform.stream.StreamSource;
import javax.xml.ws.EndpointReference;
import javax.xml.ws.wsaddressing.W3CEndpointReference;

import eu.dnetlib.enabling.is.sn.SubscriptionRequest;
import org.apache.commons.lang3.builder.EqualsBuilder;
import org.apache.commons.lang3.builder.HashCodeBuilder;

/**
 * This class describes a ResourceState subscription, i.e. a subscription that is registered on a topic that depends on
 * some xpath on some resource, and which is triggered when the value of this xpath changes.
 * 
 * Topics of this type could not be there.
 * 
 * @author marko
 * 
 */
@Entity(name = "subscriptions")
@Table(name = "subscriptions")
public class ResourceStateSubscription {

	/**
	 * hash seed.
	 */
	private static final int HASH_SEED_2 = 59;

	/**
	 * hash seed.
	 */
	private static final int HASH_SEED = 47;

	/**
	 * create topic prefix.
	 */
	public static final String PREFIX_CREATE = "CREATE";

	/**
	 * delete topic prefix.
	 */
	public static final String PREFIX_DELETE = "DELETE";

	/**
	 * update topic prefix.
	 */
	public static final String PREFIX_UPDATE = "UPDATE";
	
	/**
	 * pending create topic prefix.
	 */
	public static final String PREFIX_PENDING_CREATE = "PENDING_CREATE";

	/**
	 * pending delete topic prefix.
	 */
	public static final String PREFIX_PENDING_DELETE = "PENDING_DELETE";

	/**
	 * pending update topic prefix.
	 */
	public static final String PREFIX_PENDING_UPDATE = "PENDING_UPDATE";

	
	/**
	 * subscription identifier.
	 */
	@Id
    @Column(name = "subscriptionid")
	private String subscriptionId;

	/**
	 * prefix: crude.
	 */
	@Column(name = "prefix")
	private String prefix;
	
	/**
	 * resource type.
	 */
	@Column(name = "type")
	private String type;

	/**
	 * resource id.
	 */
	@Column(name = "resourceid")
	private String resourceId;

	/**
	 * xpath.
	 */
	@Column(name = "xpath")
	private String xpath;

	/**
	 * consumer (subscriber) reference.
	 */
	@Column(name = "subscriber", length = 4096)	
	private String subscriber;

	/**
	 * default constructor. for unit testing.
	 */
	public ResourceStateSubscription() {
		this.type = "*";
		this.resourceId = "*";
	}

	/**
	 * create a new instance.
	 * 
	 * @param request
	 *            original request.
	 * @param prefix
	 *            prefix
	 * @param type
	 *            resource type
	 * @param resourceId
	 *            resource identifier
	 * @param xpath
	 *            xpath
	 */
	public ResourceStateSubscription(final SubscriptionRequest request, final String prefix, final String type, final String resourceId,
			final String xpath) {
		super();
		setSubscriptionId(request.getSubscriptionId());
		setSubscriber(request.getSubscriber());
		setPrefix(prefix);
		setType(type);
		setResourceId(resourceId);
		setXpath(xpath);
	}

	/**
	 * {@inheritDoc}
	 * 
	 * @see java.lang.Object#hashCode()
	 */
	@Override
	public int hashCode() {
		return new HashCodeBuilder(HASH_SEED, HASH_SEED_2).append(subscriptionId).append(subscriber.toString()).append(prefix).append(type).append(xpath)
				.toHashCode();
	}

	/**
	 * {@inheritDoc}
	 * 
	 * @see java.lang.Object#equals(java.lang.Object)
	 */
	@Override
	public boolean equals(final Object obj) {
		if (!(obj instanceof ResourceStateSubscription))
			return false;

		if (this == obj)
			return true;

		final ResourceStateSubscription rhs = (ResourceStateSubscription) obj;
		return new EqualsBuilder().append(subscriptionId, rhs.getSubscriptionId()).append(prefix, rhs.getPrefix()).append(
				resourceId, rhs.getResourceId()).append(xpath, rhs.getXpath()).isEquals();
	}

	public String getSubscriptionId() {
		return subscriptionId;
	}

	public void setSubscriptionId(final String subscriptionId) {
		this.subscriptionId = subscriptionId;
	}

	public String getPrefix() {
		return prefix;
	}

	public void setPrefix(final String prefix) {
		this.prefix = prefix;
	}

	public String getType() {
		return type;
	}

	public void setType(final String type) {
		this.type = type == null || type.isEmpty() ? "*" : type;
	}

	public String getXpath() {
		return xpath;
	}

	public void setXpath(final String xpath) {
		this.xpath = xpath;
	}

	public String getSubscriber() {
		return subscriber;
	}

	public W3CEndpointReference getSubscriberAsEpr() {
		return (W3CEndpointReference) EndpointReference.readFrom(new StreamSource(new StringReader(getSubscriber())));
	}

	public void setSubscriber(final W3CEndpointReference epr) {
		this.subscriber = (epr != null) ? epr.toString() : null;;
	}

	public void setSubscriber(final String subscriber) {
		this.subscriber = subscriber;
	}

	public void setResourceId(final String resourceId) {
		this.resourceId = resourceId == null || resourceId.isEmpty() ? "*" : resourceId;
	}

	public String getResourceId() {
		return resourceId;
	}

}
