package com.netflix.evcache.pool;

import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.util.List;

import com.netflix.appinfo.InstanceInfo;
import com.netflix.config.ChainedDynamicProperty;
import com.netflix.discovery.DiscoveryClient;
import com.netflix.discovery.shared.Application;
import com.netflix.evcache.util.EVCacheConfig;

import net.spy.memcached.MemcachedNode;
import net.spy.memcached.util.DefaultKetamaNodeLocatorConfiguration;

public class EVCacheKetamaNodeLocatorConfiguration extends DefaultKetamaNodeLocatorConfiguration {

    private final String appId;
    private final ServerGroup serverGroup;
    private final EVCacheClientPoolManager poolManager;

    private final ChainedDynamicProperty.IntProperty bucketSize;

    public EVCacheKetamaNodeLocatorConfiguration(String appId, ServerGroup serverGroup, EVCacheClientPoolManager poolManager) {
        this.appId = appId;
        this.serverGroup = serverGroup;
        this.poolManager = poolManager;
        bucketSize = EVCacheConfig.getInstance().getChainedIntProperty(appId + "." + serverGroup.getName() + ".bucket.size",appId + ".bucket.size", super.getNodeRepetitions(), null);
    }

    /**
     * Returns the number of discrete hashes that should be defined for each
     * node in the continuum.
     *
     * @return NUM_REPS repetitions.
     */
    public int getNodeRepetitions() {
        return bucketSize.get().intValue();
    }

    /**
     * Returns the socket address of a given MemcachedNode.
     *
     * @param node - The MemcachedNode which we're interested in
     * @return The socket address of the given node format is of the following
     * format "publicHostname/privateIp:port" (ex -
     ec2-174-129-159-31.compute-1.amazonaws.com/10.125.47.114:11211)
     */
    @Override
    protected String getSocketAddressForNode(MemcachedNode node) {
        String result = socketAddresses.get(node);
        if(result == null) {
            final SocketAddress socketAddress = node.getSocketAddress();
            if(socketAddress instanceof InetSocketAddress) {
                final InetSocketAddress isa = (InetSocketAddress)socketAddress;
                if(poolManager.getDiscoveryClient() != null ) {
                    final DiscoveryClient mgr = poolManager.getDiscoveryClient();
                    final Application app = mgr.getApplication(appId);
                    if(app != null) {
	                    final List<InstanceInfo> instances = app.getInstances();
	                    for(InstanceInfo info : instances) {
	                        final String hostName = info.getHostName();
	                        if(hostName.equalsIgnoreCase(isa.getHostName())) {
	                            final String ip = info.getIPAddr();
	                            final String port = info.getMetadata().get("evcache.port");
	                            result = hostName + '/' + ip + ':' + ((port != null) ? port : "11211");
	                            break;
	                        }
	                    }
                    } else {
                    	result = ((InetSocketAddress)socketAddress).getHostName() + '/' + ((InetSocketAddress)socketAddress).getAddress().getHostAddress() + ":11211";
                    }
                } else {
                    result = ((InetSocketAddress)socketAddress).getHostName() + '/' + ((InetSocketAddress)socketAddress).getAddress().getHostAddress() + ":11211";
                }
            } else {
                result=String.valueOf(socketAddress);
                if (result.startsWith("/")) {
                    result = result.substring(1);
                }
            }
            socketAddresses.put(node, result);
        }
        return result;
    }

    @Override
    public String toString() {
        return "EVCacheKetamaNodeLocatorConfiguration [app=" + appId + ", ServerGroup=" + serverGroup + ", BucketSize=" + getNodeRepetitions() + "]";
    }
}
@@ -758,16 +758,83 @@
 ketSize;
+%0A    private final ChainedDynamicProperty.BooleanProperty isSecure;
 %0A%0A    pu
@@ -1246,16 +1246,352 @@
  null);%0A
+        final Runnable callback =new Runnable() %7B%0A            public void run() %7B%0A                poolManager.getEVCacheClientPool(appId).refreshPool();%0A            %7D%0A        %7D; %0A%0A        isSecure = EVCacheConfig.getInstance().getChainedBooleanProperty(this.serverGroup.getName() + %22.is.secure%22, appId + %22.is.secure%22, false, callback);%0A
     %7D%0A%0A 
@@ -3194,30 +3194,24 @@
             
-final 
 String port 
@@ -3248,24 +3248,150 @@
 che.port%22);%0A
+%09                            if(port == null) port = %2211211%22;%0A%09                            if(isSecure.get()) port = %2211443%22;%0A
 %09           
@@ -3448,41 +3448,12 @@
 ' + 
-((
 port
- != null) ? port : %2211211%22)
 ;%0A%09 
@@ -3557,32 +3557,112 @@
        %7D else %7B%0A
+                        final String port = isSecure.get() ? %2211443%22 : %2211211%22;%0A
                 
@@ -3793,38 +3793,40 @@
 stAddress() + %22:
-11211%22
+%22 + port
 ;%0A              
@@ -3850,32 +3850,108 @@
        %7D else %7B%0A
+                    final String port = isSecure.get() ? %2211443%22 : %2211211%22;%0A
                 
@@ -4088,19 +4088,22 @@
 ss()
+ 
  + %22:
-11211%22
+%22 + port
 ;%0A  

Support for secure port