
package eu.neclab.iotplatform.iotbroker.core.subscription;

import java.net.InetAddress;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.UnknownHostException;
import java.util.List;
import java.util.TimerTask;

import org.apache.log4j.Logger;

import eu.neclab.iotplatform.iotbroker.commons.Restriction;
import eu.neclab.iotplatform.ngsi.api.datamodel.NotifyContextRequest;
import eu.neclab.iotplatform.ngsi.api.datamodel.QueryContextResponse;
import eu.neclab.iotplatform.ngsi.api.datamodel.SubscribeContextRequest;

/**
 * Represents the recurring task for sending notifications in reaction to
 * subscriptions.
 * 
 * Usually this task is created by the NorthBoundWrapper when it receive a
 * Subscripiton request from the North (i.e. from an Application)
 */
public class ThrottlingTask extends TimerTask {
	private static Logger logger = Logger.getLogger(ThrottlingTask.class);
	private final String subId;
	private final SubscriptionController subContoller;

	/**
	 * Creates a new task instance.
	 * 
	 * @param subId
	 *            The identifier of this subscription.
	 * @param subscriptionController
	 *            Pointer to the subscription controller.
	 */
	public ThrottlingTask(String subId,
			SubscriptionController subscriptionController) {
		this.subId = subId;
		subContoller = subscriptionController;
	}

	/**
	 * @return The identifier of the subscription.
	 */
	public String getSubId() {
		return subId;
	}

	/**
	 * Flushes the notification queue for a subscription.
	 */
	@Override
	public void run() {

		/*
		 * Retrieve the subscription data from the subscription store
		 */

		logger.debug("SubscriptionId from TrottlingTask ---------------->"
				+ subId);

		SubscriptionData subscriptionData = subContoller.getSubscriptionStore()
				.get(subId);

		logger.debug("Trotthling task ID ---------------->"
				+ subscriptionData.getThrottlingTask().getSubId());

		if (subscriptionData.getContextResponseQueue().isEmpty()) {
			logger.debug("Terminating notification task as there are no notifications to send.");
			return;
		}

		try {

			/*
			 * Lock this subscription data so that no one can add notifications
			 * to it while sending the notifications.
			 */

			subscriptionData.getLock().lock();
			logger.debug("subscription ID to notify: " + subId);

			/*
			 * Get the availability subscription
			 */
			List<String> subIdAgent = subContoller.getLinkAvSub().getAvailIDs(
					subId);
			logger.debug("Number of availability subscriptions corresponding to the incoming:"
					+ subIdAgent.size());
			logger.debug("First availability subscription:" + subIdAgent.get(0));

			/*
			 * Get the incoming subscription
			 */
			SubscribeContextRequest request = subContoller.getIncomingSub()
					.getIncomingSubscription(subId);

			logger.debug("Processing Notication for this subscription:"
					+ request.toString());

			NotifyContextRequest notifyReq = null;

			logger.debug("Notification queue: "
					+ subscriptionData.getContextResponseQueue().toString());

			/*
			 * Create a query context response from the context element
			 * responses in the notification queue
			 */
			QueryContextResponse qcr = new QueryContextResponse();
			qcr.setContextResponseList(subscriptionData
					.getContextResponseQueue());

			/*
			 * Apply the restriction if there is any
			 */
			if (request.getRestriction() != null
					&& request.getRestriction().getAttributeExpression() != null
					&& !request.getRestriction().getAttributeExpression()
							.isEmpty()) {
				Restriction.applyRestriction(request.getRestriction()
						.getAttributeExpression(), qcr);
			}

			logger.info("Notification queue after applying restriction: "
					+ qcr.getListContextElementResponse());

			/*
			 * Create the notification request
			 */
			String originator = subscriptionData.getOriginator();
			notifyReq = new NotifyContextRequest(subId, originator,
					qcr.getListContextElementResponse());
			// notifyReq = new NotifyContextRequest(subId,
			// "http://" + InetAddress.getLocalHost().getHostAddress()
			// + ":" + System.getProperty("tomcat.init.port")
			// + "/ngsi10/notify",
			// qcr.getListContextElementResponse());

			logger.info("Now sending this notification:" + notifyReq);

			subContoller.getNorthBoundWrapper().forwardNotification(notifyReq,
					new URI(subscriptionData.getNotificationHandler()));

			// } catch (UnknownHostException e) {
			// logger.info("Unknown host, aborting notification", e);
		} catch (URISyntaxException e) {
			logger.info("Error in URI Syntax", e);
		} finally {
			// Clear the notification list and unlock
			subscriptionData.getContextResponseQueue().clear();
			subscriptionData.getLock().unlock();

		}

	}

}
