/*
 * 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.client;

import java.util.concurrent.ConcurrentHashMap;

import flex.messaging.MessageClient.SubscriptionInfo;
import flex.messaging.config.ThrottleSettings.Policy;
import flex.messaging.log.Log;
import flex.messaging.messages.Message;
import flex.messaging.services.messaging.MessageFrequency;
import flex.messaging.services.messaging.ThrottleManager;
import flex.messaging.services.messaging.ThrottleManager.ThrottleResult;
import flex.messaging.util.StringUtils;


/**
 * Used to keep track of and limit outbound message rates of a single FlexClient queue.
 * An outbound FlexClient queue can contain messages from multiple MessageClients
 * across multiple destinations. It can also contain messages for multiple
 * subscriptions (for each subtopic/selector) across the same destination for
 * the same MessageClient.
 */
public class OutboundQueueThrottleManager
{
    //--------------------------------------------------------------------------
    //
    // Constructor
    //
    //--------------------------------------------------------------------------

    /**
     * Constructs a default outbound queue throttle manager.
     *
     * @param processor The outbound queue processor that is using this throttle manager.
     */
    public OutboundQueueThrottleManager(FlexClientOutboundQueueProcessor processor)
    {
        destinationFrequencies = new ConcurrentHashMap<String, DestinationFrequency>();
        this.processor = processor;
    }

    //--------------------------------------------------------------------------
    //
    // Variables
    //
    //--------------------------------------------------------------------------

    /**
     * Map of destination id and destination message frequencies.
     */
    protected final ConcurrentHashMap<String, DestinationFrequency> destinationFrequencies;

    /**
     * The parent queue processor of the throttle manager.
     */
    protected final FlexClientOutboundQueueProcessor processor;

    //--------------------------------------------------------------------------
    //
    // Public Methods
    //
    //--------------------------------------------------------------------------

    /**
     * Registers the destination with the outbound throttle manager.
     *
     * @param destinationId The id of the destination.
     * @param outboundMaxClientFrequency The outbound max-client-frequency specified
     * at the destination.
     * @param outboundPolicy The outbound throttle policy specified at the destination.
     */
    public void registerDestination(String destinationId, int outboundMaxClientFrequency, Policy outboundPolicy)
    {
        DestinationFrequency frequency = destinationFrequencies.get(destinationId);
        if (frequency == null)
        {
            frequency = new DestinationFrequency(outboundMaxClientFrequency, outboundPolicy);
            destinationFrequencies.putIfAbsent(destinationId, frequency);
        }
    }

    /**
     * Registers the subscription of a client talking to a destination with the
     * specified subscription info.
     *
     * @param destinationId The destination id.
     * @param si The subscription information.
     */
    public void registerSubscription(String destinationId, SubscriptionInfo si)
    {
        DestinationFrequency frequency = destinationFrequencies.get(destinationId);
        frequency.logMaxFrequencyDuringRegistration(frequency.outboundMaxClientFrequency, si);
    }

    /**
     * Unregisters the subscription.
     *
     * @param destinationId The destination id.
     * @param si The subscription information.
     */
    public void unregisterSubscription(String destinationId, SubscriptionInfo si)
    {
        unregisterDestination(destinationId);
    }

    /**
     * Unregisters all subscriptions of the client under the specified destination.
     *
     * @param destinationId The destination id.
     */
    public void unregisterAllSubscriptions(String destinationId)
    {
        unregisterDestination(destinationId);
    }

    /**
     * Attempts to throttle the outgoing message.
     *
     * @param message The message to consider to throttle.
     * @return True if the message was throttled; otherwise false.
     */
    public ThrottleResult throttleOutgoingClientLevel(Message message)
    {
        String destinationId = message.getDestination();
        if (isDestinationRegistered(destinationId))
        {
            DestinationFrequency frequency = destinationFrequencies.get(message.getDestination());
            int maxFrequency = frequency.getMaxFrequency(message); // Limit to check against.
            MessageFrequency messageFrequency = frequency.getMessageFrequency(message); // Message rate of the client.
            if (messageFrequency != null)
            {
                ThrottleResult result = messageFrequency.checkLimit(maxFrequency, frequency.outboundPolicy);
                return result;
            }
        }
        return new ThrottleResult(); // Otherwise, return OK result.
    }

    /**
     * Updates the outgoing client level message frequency of the message.
     *
     * @param message The message.
     */
    public void updateMessageFrequencyOutgoingClientLevel(Message message)
    {
        String destinationId = message.getDestination();
        if (isDestinationRegistered(destinationId))
        {
            DestinationFrequency frequency = destinationFrequencies.get(message.getDestination());
            MessageFrequency messageFrequency = frequency.getMessageFrequency(message);
            if (messageFrequency != null)
                messageFrequency.updateMessageFrequency();
        }
    }

    //--------------------------------------------------------------------------
    //
    // Protected Methods
    //
    //--------------------------------------------------------------------------

    /**
     * Determines whether the destination has been registered or not.
     *
     * @param destinationId The destination id.
     * @return True if the destination with the specified id has been registered.
     */
    protected boolean isDestinationRegistered(String destinationId)
    {
        return destinationFrequencies.containsKey(destinationId);
    }

    /**
     * Unregisters the destination from the outbound throttle manager.
     *
     * @param destinationId The id of the destination.
     */
    protected void unregisterDestination(String destinationId)
    {
        if (isDestinationRegistered(destinationId))
            destinationFrequencies.remove(destinationId);
    }

    //--------------------------------------------------------------------------
    //
    // Inner Classes
    //
    //--------------------------------------------------------------------------

    /**
     * Used to keep track of max-client-frequency and outgoing throttle policy
     * specified at the destination. It also keeps track of outbound message
     * rates of all MessageClient subscriptions across the destination.
     */
    class DestinationFrequency
    {
        protected final int outboundMaxClientFrequency; // destination specified client limit.
        protected final MessageFrequency outboundClientFrequency;
        protected final Policy outboundPolicy; // destination specified policy.

        /**
         * Default constructor.
         *
         * @param outboundMaxClientFrequency The outbound throttling max-client-frequency of the destination.
         * @param outboundPolicy The outbound throttling policy of the destination.
         */
        DestinationFrequency(int outboundMaxClientFrequency, Policy outboundPolicy)
        {
            this.outboundMaxClientFrequency = outboundMaxClientFrequency;
            this.outboundPolicy = outboundPolicy;
            outboundClientFrequency = new MessageFrequency(outboundMaxClientFrequency);
        }

        /**
         * Returns the max-client-frequency for the subscription the message is
         * intended for (which is simply the max-client-frequency specified at 
         * the destination).
         *
         * @param message The message.
         *
         * @return The max-frequency for the subscription.
         */
        int getMaxFrequency(Message message)
        {
            return outboundMaxClientFrequency;
        }

        /**
         * Given a subscription the message is intended to, returns the message
         * rate frequency for that subscription.
         *
         * @param message The message.
         * @return The message frequency for the subscription, if it exists; otherwise null.
         */
        MessageFrequency getMessageFrequency(Message message)
        {
            return outboundClientFrequency;
        }

        /**
         * Utility function to log the maxFrequency being used during subscription.
         *
         * @param maxFrequency The maxFrequency to log.
         */
        void logMaxFrequencyDuringRegistration(int maxFrequency, SubscriptionInfo si)
        {
            if (Log.isDebug())
                Log.getLogger(ThrottleManager.LOG_CATEGORY).debug("Outbound queue throttle manager for FlexClient '"
                        + processor.getFlexClient().getId() + "' is using '" + maxFrequency
                        + "' as the throttling limit for its subscription: "
                        +  StringUtils.NEWLINE + si);
        }
    }
}