/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You 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 flex.messaging.services.messaging;

import flex.messaging.MessageDestination;
import flex.messaging.MessageClient;
import flex.messaging.services.MessageService;
import flex.messaging.log.Log;
import flex.messaging.util.StringUtils;
import flex.messaging.cluster.RemoveNodeListener;

import java.util.List;

/**
 * The RemoteSubscriptionManager monitors subscriptions from other
 * servers, not other clients.  One MessageClient instance is used for
 * each remote server.  It clientId is the address of the remote server.
 * Using a separate instance of this class keeps the subscriptions
 * of local clients separate from remote clients.
 *
 *
 */
public class RemoteSubscriptionManager extends SubscriptionManager implements RemoveNodeListener
{
    private Object syncLock = new Object();

    /*
     * A monitor lock used for synchronizing the attempt to request subscriptions
     * across the cluster during startup.
     */
    private static final Object initRemoteSubscriptionsLock = new Object();

    public RemoteSubscriptionManager(MessageDestination destination)
    {
        this(destination, false);
    }

    public RemoteSubscriptionManager(MessageDestination destination, boolean enableManagement)
    {
        super(destination, enableManagement);
    }

    public void setSessionTimeout(long sessionConfigValue)
    {
    }

    public long getSessionTimeout()
    {
        return 0; // not used for remote subscriptions
    }

    public void addSubscriber(String flexClientId, Object clientId, String selector, String subtopic)
    {
        synchronized (syncLock)
        {
            /*
             * Only process subscriptions for servers whose subscription state we have received
             * We may receive a subscribe/unsubscribe from a peer before we get their
             * subscription state... we ignore these since they will be included in the
             * state we receive later
             */
            if (allSubscriptions.get(clientId) != null)
                super.addSubscriber(clientId, selector, subtopic, null);
            else if (Log.isDebug())
                Log.getLogger(MessageService.LOG_CATEGORY).debug("Ignoring new remote subscription for server: " + clientId + " whose subscription state we have not yet received.  selector: " + selector + " subtopic: " + subtopic);
        }
    }

    public void removeSubscriber(String flexClientId, Object clientId, String selector, String subtopic, String endpoint)
    {
        synchronized (syncLock)
        {
            /* Only process subscriptions for servers whose subscription state we have received */
            if (allSubscriptions.get(clientId) != null)
                super.removeSubscriber(clientId, selector, subtopic, null);
        }
    }

    protected void sendSubscriptionToPeer(boolean subscribe, String selector, String subtopic)
    {
        // Don't do this for remote subscriptions
    }

    protected MessageClient newMessageClient(Object clientId, String endpointId)
    {
        return new RemoteMessageClient(clientId, destination, endpointId);
    }

    /**
     * Takes the selector and subtopic list from this address and
     * for each one create a RemoteSubscription which gets
     * registered in this table.  We also register the remote
     * subscription with a "per server" index so we can easily
     * remove them later on.
     * @param state the subscription state object
     * @param address the remote cluster node address
     */
    public void setSubscriptionState(Object state, Object address)
    {
        MessageClient client = newMessageClient(address, null);

        if (Log.isDebug())
            Log.getLogger(MessageService.LOG_CATEGORY).debug("Received subscription state for destination: " + destination.getId() + " from server: " + address + StringUtils.NEWLINE + state);

        /*
         * need to be sure we do not accept any remote sub/unsub messages
         * from a given server until we have received its subscription state
         *
         * Also, we need to ensure we do not process any remote subscribe/unsubs
         * from a remote server until we finish this list.
         */
        synchronized (syncLock)
        {
            allSubscriptions.put(address, client);

            List list = (List) state;

            for (int i = 0; i < list.size(); i+=2)
            {
                addSubscriber(null, address, (String) list.get(i), (String) list.get(i+1));
            }
        }
        synchronized (initRemoteSubscriptionsLock)
        {
            initRemoteSubscriptionsLock.notifyAll();
        }
    }

    /**
     * This method waits for some time for the receipt of the subscription
     * state for the server with the given address.  If we fail to receive
     * a message after waiting for the 5 seconds, a warning is printed.
     * @param addr the remote cluster node address
     */
    public void waitForSubscriptions(Object addr)
    {
        /* If we have not gotten the response yet from this client... */
        if (getSubscriber(addr) == null)
        {
            synchronized (initRemoteSubscriptionsLock)
            {
                try
                {
                    if (Log.isDebug())
                        Log.getLogger(MessageService.LOG_CATEGORY).debug("Waiting for subscriptions from cluster node: " + addr + " for destination: " + destination.getId());

                    initRemoteSubscriptionsLock.wait(5000);

                    if (Log.isDebug())
                        Log.getLogger(MessageService.LOG_CATEGORY).debug("Done waiting for subscriptions from cluster node: " + addr + " for destination: " + destination.getId());
                }
                catch (InterruptedException exc) {}
            }
            if (getSubscriber(addr) == null && Log.isWarn())
                Log.getLogger(MessageService.LOG_CATEGORY).warn("No response yet from request subscriptions request for server: " + addr + " for destination: " + destination.getId());
        }
        else if (Log.isDebug())
            Log.getLogger(MessageService.LOG_CATEGORY).debug("Already have subscriptions from server: " + addr + " for destination: " + destination.getId());
    }

    /**
     * Called when a cluster node gets removed.  We need to make sure that all subscriptions
     * for this node are removed.
     * @param address the remote cluster node address
     */
    public void removeClusterNode(Object address)
    {
        if (Log.isDebug())
            Log.getLogger(MessageService.LOG_CATEGORY).debug("Cluster node: " + address + " subscriptions being removed for destination:" + destination.getId() + " before: " + StringUtils.NEWLINE + getDebugSubscriptionState());

        MessageClient client = getSubscriber(address);
        if (client != null)
        {
            client.invalidate();
        }

        if (Log.isDebug())
            Log.getLogger(MessageService.LOG_CATEGORY).debug("Cluster node: " + address + " subscriptions being removed for destination:" + destination.getId() + " after: " + StringUtils.NEWLINE + getDebugSubscriptionState());
    }

    protected void monitorTimeout(MessageClient client)
    {
        // Remote subscriptions do not timeout
    }

}
