package eu.dnetlib.functionality.alert.alerter.atom;

import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.Date;
import java.util.SortedSet;
import java.util.TreeSet;
import java.util.UUID;

import org.apache.log4j.Logger;

import eu.dnetlib.domain.functionality.AlertSubscription;
import eu.dnetlib.domain.functionality.ObjectPage;
import eu.dnetlib.functionality.alert.alerter.Alerter;
import eu.dnetlib.functionality.alert.alerter.AlerterException;
import eu.dnetlib.functionality.alert.alerter.atom.domain.AtomEntry;
import eu.dnetlib.functionality.alert.alerter.atom.domain.AtomFeed;

/**
 * This class implements an alerter that is capable of publishing alerts as Atom 1.0 feed entries.
 * The subscribers served by this alerter must have a URI that is a valid URN, which is the ID of the Atom 1.0 feed to publish to.
 * @author thanos@di.uoa.gr
 * @see Alerter
 * @see eu.dnetlib.domain.functionality.AlertTopic
 * @see eu.dnetlib.domain.functionality.AlertSubscription
 * @see AlerterException
 * 
 */

public class AtomAlerter extends Alerter {
	private static final Logger logger = Logger.getLogger(AtomAlerter.class);
	private static final String ATOM = "Atom";
	private static final String URN = "urn";
	private static final SortedSet<String> SUPPORTED_ALERT_MODES = new TreeSet<String>();
	private static final SortedSet<String> SUPPORTED_URI_SCHEMES = new TreeSet<String>();
	
	private AtomAlerterTransactionHelper transactionHelper;
	private String authorName;
	private String authorEmail;
	private int pageSize;
	
	static {
		SUPPORTED_ALERT_MODES.add(ATOM);
		SUPPORTED_URI_SCHEMES.add(URN);
	}
	
	/**
	 * Set transaction helper.
	 * @param transactionHelper the transaction helper to use
	 */
	public void setTransactionHelper(final AtomAlerterTransactionHelper transactionHelper) {
		this.transactionHelper = transactionHelper;
	}
	
	/**
	 * Get author name.
	 * @return the author name to use
	 */
	public String getAuthorName() {
		return authorName;
	}
	
	/**
	 * Set the author name.
	 * @param authorName the author name to use
	 */
	public void setAuthorName(final String authorName) {
		this.authorName = authorName;
	}
	
	/**
	 * Get the author email.
	 * @return the author email to use
	 */
	public String getAuthorEmail() {
		return authorEmail;
	}
	
	/**
	 * Set the author email.
	 * @param authorEmail the author email to use
	 */
	public void setAuthorEmail(final String authorEmail) {
		this.authorEmail = authorEmail;
	}
	
	/**
	 * Get the page size.
	 * @return the page size to use
	 */
	public int getPageSize() {
		return pageSize;
	}
	
	/**
	 * Set the page size.
	 * @param pageSize the page size to use
	 */
	public void setPageSize(final int pageSize) {
		this.pageSize = pageSize;
	}
	
	/**
	 * Retrieve a page of feeds.
	 * @param pageNumber the number of the page to retrieve 
	 * @param pageSize the size of the page to retrieve
	 * @return an object page containing feeds
	 * @throws AlerterException if any errors occur
	 */
	public ObjectPage<AtomFeed> getFeeds(final int pageNumber, final int pageSize) throws AlerterException {
		return transactionHelper.getFeeds(pageNumber, pageSize);
	}
	
	/**
	 * Retrieve a feed.
	 * @param id the URN that uniquely identifies the feed to retrieve
	 * @return the feed specified or null if no such feed exists
	 * @throws AlerterException if any errors occur
	 */
	public AtomFeed getFeed(final URI id) throws AlerterException {
		return transactionHelper.getFeed(id);
	}
	
	/**
	 * Add a feed.
	 * @param feed the feed to add
	 * @throws AlerterException if any errors occur
	 */
	public void addFeed(final AtomFeed feed) throws AlerterException {
		transactionHelper.addFeed(feed);
	}
	
	/**
	 * Remove a feed.
	 * @param id the URN that uniquely identifies the feed to remove
	 * @throws AlerterException if any errors occur
	 */
	public void removeFeed(final URI id) throws AlerterException {
		transactionHelper.removeFeed(id);
	}
	
	/**
	 * Retrieve some entries of a feed.
	 * @param feed the URN that uniquely identifies the feed of the entries to retrieve
	 * @param limit the maximum number of feeds to retrieve
	 * @param offset the offset to start at
	 * @return a sorted set containing feeds
	 * @throws AlerterException if any errors occur
	 */
	public SortedSet<AtomEntry> getEntries(final URI feed, final int limit, final int offset) throws AlerterException {
		return transactionHelper.getEntries(feed, limit, offset);
	}
	
	@Override
	public void init() throws AlerterException {
		logger.info("Atom alerter initialization complete");
	}

	@Override
	public SortedSet<String> getSupportedAlertModes() {
		return SUPPORTED_ALERT_MODES;
	}

	@Override
	public void alert(final AlertSubscription subscription, final String title, final String message, final URL link) throws AlerterException {
		validateSubscription(subscription);
		try {
			transactionHelper.addEntry(new AtomEntry(subscription.getSubscriber(), new URI("urn:uuid:" + UUID.randomUUID()), title, new Date(), message, link));
		} catch (final URISyntaxException e) {
			logger.info("Error posting alert to " + subscription.getSubscriber(), e);
		}
	}

	@Override
	protected SortedSet<String> getSupportedUriSchemes() {
		return SUPPORTED_URI_SCHEMES;
	}
}
