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

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

/**
 * ClusterNode is an encapsulation for pairing a physical host and a logical
 * software group, which is in effect a mapping between a physical address used
 * by the cluster infrastructure and a service destination used by the message
 * infrastructure.
 * <p>
 * This class is specific to the <code>JGroupsCluster</code> implementation.
 */
public class ClusterNode {
    /**
     * The name of the host for this cluster node.
     */
    private final String host;

    /**
     * Mapping between clustered destinations and the
     * clustered endpoint.
     * key = destination key (String)
     * value = Map of channel-id to endpoint-url mappings.
     */
    private final Map<String, Map<String, String>> destKeyToChannelMap;

    /**
     * Constructor.
     */
    ClusterNode(String host) {
        this.host = host;
        destKeyToChannelMap = new HashMap<String, Map<String, String>>();
    }

    /**
     * Returns the name of the host for this cluster node.
     *
     * @return The name of the host.
     */
    String getHost() {
        return host;
    }

    /**
     * Returns a map of clustered destination to clustered
     * endpoint mappings.
     *
     * @return Map of clustered destination to clustered
     * endpoint mappings.
     */
    Map<String, Map<String, String>> getDestKeyToChannelMap() {
        return destKeyToChannelMap;
    }

    /**
     * Returns a map of clustered endpoints for the specified
     * clustered destination. If there is not currently a
     * map for the destination, an empty mapping is created
     * and returned.
     * <p>
     * The endpoint map is indexed by channel id.
     * The endpoint map contains endpoint urls.
     *
     * @param serviceType The service type of the clustered destination.
     * @param destName    The destination name of the clustered destination.
     * @return Map of clustered endpoints.
     */
    Map<String, String> getEndpoints(String serviceType, String destName) {
        String destKey = serviceType + ":" + destName;
        synchronized (destKeyToChannelMap) {
            Map<String, String> channelEndpoints = destKeyToChannelMap.get(destKey);
            if (channelEndpoints == null) {
                channelEndpoints = new HashMap<String, String>();
                destKeyToChannelMap.put(destKey, channelEndpoints);
            }
            return channelEndpoints;
        }
    }

    /**
     * This method adds an endpoint to the list of endpoints for the clustered
     * destination, identified by service type and destination name.
     *
     * @param serviceType The service type of the clustered destination.
     * @param destName    The destination name of the clustered destination.
     * @param channelId   The channel id to be added to the channel endpoint mapping.
     * @param endpointUrl The endpoint url to be added to the endpoint url mapping.
     */
    void addEndpoint(String serviceType, String destName, String channelId, String endpointUrl) {
        synchronized (destKeyToChannelMap) {
            Map<String, String> channelEndpoints = getEndpoints(serviceType, destName);
            channelEndpoints.put(channelId, endpointUrl);
        }
    }

    /**
     * Returns whether the endpoint, specified by channel id and endpoint url,
     * is included in the list of endpoints in the clustered destination.
     *
     * @param serviceType The service type of the clustered destination.
     * @param destName    The destination name of the clustered destination.
     * @param channelId   The channel id to find in the list of endpoints.
     * @param endpointUrl The endpoint url to find in the list of endpoints.
     * @return Whether the endpoint is included in the list for the clustered destination.
     */
    boolean containsEndpoint(String serviceType, String destName, String channelId, String endpointUrl) {
        Map<String, String> channelEndpoints = getEndpoints(serviceType, destName);
        return channelEndpoints.containsKey(channelId) && channelEndpoints.get(channelId).equals(endpointUrl);
    }

    /**
     * Returns a description of the clustered node including details
     * on the mapping between the clustered destinations on this node
     * and their endpoint mappings.
     *
     * @return Description of the clustered node.
     */
    public String toString() {
        StringBuffer sb = new StringBuffer("ClusterNode[");
        synchronized (destKeyToChannelMap) {
            for (Map.Entry<String, Map<String, String>> entry : destKeyToChannelMap.entrySet()) {
                sb.append(" channels for ");
                sb.append(entry.getKey());
                sb.append('(');
                for (Iterator<Map.Entry<String, String>> iter = entry.getValue().entrySet().iterator(); iter.hasNext(); ) {
                    Map.Entry<String, String> channelMapEntry = iter.next();
                    sb.append(channelMapEntry.getKey());
                    sb.append('=');
                    sb.append(channelMapEntry.getValue());
                    if (iter.hasNext())
                        sb.append(", ");
                }
                sb.append(')');
            }
        }
        sb.append(" ]");
        return sb.toString();
    }
}
