/*
 * Copyright 2005 The Apache Software Foundation.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.jackrabbit.webdav.jcr.observation;

import org.apache.jackrabbit.webdav.DavException;
import org.apache.jackrabbit.webdav.DavResourceLocator;
import org.apache.jackrabbit.webdav.DavServletResponse;
import org.apache.jackrabbit.webdav.DavSession;
import org.apache.jackrabbit.webdav.jcr.JcrDavException;
import org.apache.jackrabbit.webdav.observation.EventDiscovery;
import org.apache.jackrabbit.webdav.observation.ObservationResource;
import org.apache.jackrabbit.webdav.observation.Subscription;
import org.apache.jackrabbit.webdav.observation.SubscriptionDiscovery;
import org.apache.jackrabbit.webdav.observation.SubscriptionInfo;
import org.apache.jackrabbit.webdav.observation.SubscriptionManager;
import org.apache.log4j.Logger;

import javax.jcr.RepositoryException;
import javax.jcr.observation.ObservationManager;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;

/**
 * <code>SubscriptionManager</code> collects all subscriptions requested, handles
 * the subscription timeout and provides METHODS to discover subscriptions
 * present on a given resource as well as events for an specific subscription.
 *
 * @todo make sure all expired subscriptions are removed!
 */
public class SubscriptionManagerImpl implements SubscriptionManager {

    private static Logger log = Logger.getLogger(SubscriptionManager.class);

    /**
     * Map containing all {@link org.apache.jackrabbit.webdav.observation.Subscription subscriptions}.
     */
    private final SubscriptionMap subscriptions = new SubscriptionMap();

    /**
     * Retrieve the {@link org.apache.jackrabbit.webdav.observation.SubscriptionDiscovery} object for the given
     * resource. Note, that the discovery object will be empty if there are
     * no subscriptions present.
     *
     * @param resource
     * @todo is it correct to return subscriptions made by another session?
     */
    public SubscriptionDiscovery getSubscriptionDiscovery(ObservationResource resource) {
        Subscription[] subsForResource = subscriptions.getByPath(resource.getLocator());
        return new SubscriptionDiscovery(subsForResource);
    }

    /**
     * Create a new <code>Subscription</code> or update an existing <code>Subscription</code>
     * and add it as eventlistener to the {@link javax.jcr.observation.ObservationManager}.
     *
     * @param info
     * @param subscriptionId
     * @param resource
     * @return <code>Subscription</code> that has been added to the {@link javax.jcr.observation.ObservationManager}
     * @throws DavException if the subscription fails
     */
    public Subscription subscribe(SubscriptionInfo info, String subscriptionId,
                                  ObservationResource resource)
            throws DavException {

        SubscriptionImpl subscription;
        DavSession session = resource.getSession();
        if (subscriptionId == null) {
            // new subscription
            subscription = new SubscriptionImpl(info, resource);
            registerSubscription(subscription, session);

            // ajust references to this subscription
            subscriptions.put(subscription.getSubscriptionId(), subscription);
            session.addReference(subscription.getSubscriptionId());
        } else {
            // refresh/modify existing one
            subscription = validate(subscriptionId, resource);
            subscription.setInfo(info);
            registerSubscription(subscription, session);
        }
        return subscription;
    }

    /**
     * Register the event listener defined by the given subscription to the
     * repository's observation manager.
     *
     * @param subscription
     * @param session
     * @throws DavException
     */
    private void registerSubscription(SubscriptionImpl subscription, DavSession session)
            throws DavException {
        try {
            ObservationManager oMgr = session.getRepositorySession().getWorkspace().getObservationManager();
            String itemPath = subscription.getLocator().getJcrPath();
            oMgr.addEventListener(subscription, subscription.getEventTypes(),
                    itemPath, subscription.isDeep(),
                    subscription.getUuidFilters(),
                    subscription.getNodetypeNameFilters(),
                    subscription.isNoLocal());
        } catch (RepositoryException e) {
            log.error("Unable to register eventlistener: "+e.getMessage());
            throw new JcrDavException(e);
        }
    }

    /**
     * Unsubscribe the <code>Subscription</code> with the given id and remove it
     * from the {@link javax.jcr.observation.ObservationManager} as well as
     * from the internal map.
     *
     * @param subscriptionId
     * @param resource
     * @throws DavException
     */
    public void unsubscribe(String subscriptionId, ObservationResource resource)
            throws DavException {

        SubscriptionImpl subs = validate(subscriptionId, resource);
        unregisterSubscription(subs, resource.getSession());
    }

    /**
     * Remove the event listener defined by the specified subscription from
     * the repository's observation manager.
     *
     * @param subscription
     * @param session
     * @throws DavException
     */
    private void unregisterSubscription(SubscriptionImpl subscription,
                                        DavSession session) throws DavException {
        try {
            session.getRepositorySession().getWorkspace().getObservationManager().removeEventListener(subscription);
            String sId = subscription.getSubscriptionId();

            // clean up any references
            subscriptions.remove(sId);
            session.removeReference(sId);

        } catch (RepositoryException e) {
            log.error("Unable to remove eventlistener: "+e.getMessage());
            throw new JcrDavException(e);
        }
    }

    /**
     * Retrieve all event bundles accumulated since for the subscription specified
     * by the given id.
     *
     * @param subscriptionId
     * @param resource
     * @return object encapsulating the events.
     */
    public EventDiscovery poll(String subscriptionId, ObservationResource resource)
            throws DavException {

        SubscriptionImpl subs = validate(subscriptionId, resource);
        return subs.discoverEvents();
    }

    /**
     * Validate the given subscription id. The validation will fail under the following
     * conditions:<ul>
     * <li>The subscription with the given id does not exist,</li>
     * <li>DavResource path does not match the subscription id,</li>
     * <li>The subscription with the given id is already expired.</li>
     * </ul>
     *
     * @param subscriptionId
     * @param resource
     * @return <code>Subscription</code> with the given id.
     * @throws DavException if an error occured while retrieving the <code>Subscription</code>
     */
    private SubscriptionImpl validate(String subscriptionId, ObservationResource resource)
            throws DavException {

        SubscriptionImpl subs;
        if (subscriptions.contains(subscriptionId)) {
            subs = (SubscriptionImpl) subscriptions.get(subscriptionId);
            if (!subs.isSubscribedToResource(resource)) {
                throw new DavException(DavServletResponse.SC_PRECONDITION_FAILED, "Attempt to operate on subscription with invalid resource path.");
            }
            if (subs.isExpired()) {
                unregisterSubscription(subs, resource.getSession());
                throw new DavException(DavServletResponse.SC_PRECONDITION_FAILED, "Attempt to  operate on expired subscription.");
            }
            return subs;
        } else {
            throw new DavException(DavServletResponse.SC_PRECONDITION_FAILED, "Attempt to modify or to poll for non-existing subscription.");
        }
    }

    /**
     * Private inner class <code>SubscriptionMap</code> that allows for quick
     * access by resource path as well as by subscription id.
     */
    private class SubscriptionMap {

        private HashMap subscriptions = new HashMap();
        private HashMap ids = new HashMap();

        private boolean contains(String subscriptionId) {
            return subscriptions.containsKey(subscriptionId);
        }

        private Subscription get(String subscriptionId) {
            return (Subscription) subscriptions.get(subscriptionId);
        }

        private void put(String subscriptionId, SubscriptionImpl subscription) {
            subscriptions.put(subscriptionId, subscription);
            DavResourceLocator key = subscription.getLocator();
            Set idSet;
            if (ids.containsKey(key)) {
                idSet = (Set) ids.get(key);
            } else {
                idSet = new HashSet();
                ids.put(key, idSet);
            }
            if (!idSet.contains(subscriptionId)) {
                idSet.add(subscriptionId);
            }
        }

        private void remove(String subscriptionId) {
            SubscriptionImpl sub = (SubscriptionImpl) subscriptions.remove(subscriptionId);
            ((Set)ids.get(sub.getLocator())).remove(subscriptionId);
        }

        private Subscription[] getByPath(DavResourceLocator locator) {
            Set idSet = (Set) ids.get(locator);
            if (idSet != null && !idSet.isEmpty()) {
                Iterator idIterator = idSet.iterator();
                Subscription[] subsForResource = new Subscription[idSet.size()];
                int i = 0;
                while (idIterator.hasNext()) {
                    subsForResource[i] = (Subscription) subscriptions.get(idIterator.next());
                }
                return subsForResource;
            } else {
                return new Subscription[0];
            }
        }
    }
}