package com.netflix.zuul.dependency.ribbon.hystrix;

import com.netflix.client.http.HttpRequest;
import com.netflix.client.http.HttpResponse;
import com.netflix.config.DynamicPropertyFactory;
import com.netflix.hystrix.HystrixCommand;
import com.netflix.hystrix.HystrixCommandGroupKey;
import com.netflix.hystrix.HystrixCommandProperties;
import com.netflix.niws.client.http.RestClient;
import com.netflix.zuul.constants.ZuulConstants;
import com.netflix.zuul.context.NFRequestContext;

import javax.ws.rs.core.MultivaluedMap;
import java.io.InputStream;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.List;

import static com.netflix.client.http.HttpRequest.Verb;

/**
 * Hystrix wrapper around Eureka Ribbon command
 *
 * @author Mikey Cohen
 *         Date: 2/6/12
 *         Time: 2:54 PM
 */
public class RibbonCommand extends HystrixCommand<HttpResponse> {

    RestClient restClient;
    Verb verb;
    URI uri;
    MultivaluedMap<String, String> headers;
    MultivaluedMap<String, String> params;
    InputStream requestEntity;


    public RibbonCommand(RestClient restClient,
                         Verb verb,
                         String uri,
                         MultivaluedMap<String, String> headers,
                         MultivaluedMap<String, String> params,
                         InputStream requestEntity) throws URISyntaxException {
        this("default", restClient, verb, uri, headers, params, requestEntity);
    }


    public RibbonCommand(String commandKey,
                         RestClient restClient,
                         Verb verb,
                         String uri,
                         MultivaluedMap<String, String> headers,
                         MultivaluedMap<String, String> params,
                         InputStream requestEntity) throws URISyntaxException {

        super(Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey(commandKey)).andCommandPropertiesDefaults(
                // we want to default to semaphore-isolation since this wraps
                // 2 others commands that are already thread isolated
                HystrixCommandProperties.Setter().withExecutionIsolationStrategy(HystrixCommandProperties.ExecutionIsolationStrategy.SEMAPHORE)
                        .withExecutionIsolationSemaphoreMaxConcurrentRequests(DynamicPropertyFactory.getInstance().
                                getIntProperty(ZuulConstants.ZUUL_EUREKA + commandKey + ".semaphore.maxSemaphores", 100).get())));

        this.restClient = restClient;
        this.verb = verb;
        this.uri = new URI(uri);
        this.headers = headers;
        this.params = params;
        this.requestEntity = requestEntity;
    }

    @Override
    protected HttpResponse run() throws Exception {
        try {
            return forward();
        } catch (Exception e) {
            throw e;
        }
    }

    HttpResponse forward() throws Exception {

        NFRequestContext context = NFRequestContext.getCurrentContext();


        HttpRequest.Builder builder = HttpRequest.newBuilder().
                verb(verb).
                uri(uri).
                entity(requestEntity);

        for (String name : headers.keySet()) {
            List<String> values = headers.get(name);
            for (String value : values) {
                builder.header(name, value);
            }
        }

        for (String name : params.keySet()) {
            List<String> values = params.get(name);
            for (String value : values) {
                builder.queryParams(name, value);
            }
        }

        HttpRequest httpClientRequest = builder.build();

        HttpResponse response = restClient.executeWithLoadBalancer(httpClientRequest);
        context.setZuulResponse(response);
        return response;
    }


}

@@ -228,16 +228,62 @@
 ommand;%0A
+import com.netflix.hystrix.HystrixCommandKey;%0A
 import c
@@ -1890,32 +1890,551 @@
 taxException %7B%0A%0A
+        this(%22default%22, RibbonCommand.class.getSimpleName(), restClient, verb, uri, headers, params, requestEntity);%0A    %7D%0A    %0A    public RibbonCommand(String groupKey, %0A                    String commandKey,%0A                    RestClient restClient,%0A                    Verb verb,%0A                    String uri,%0A                    MultivaluedMap%3CString, String%3E headers,%0A                    MultivaluedMap%3CString, String%3E params,%0A                    InputStream requestEntity) throws URISyntaxException %7B%0A        %0A
         super(Se
@@ -2488,16 +2488,73 @@
 y.asKey(
+groupKey)).andCommandKey(HystrixCommandKey.Factory.asKey(
 commandK
@@ -2588,21 +2588,16 @@
 faults(%0A
-     
         
@@ -2672,21 +2672,16 @@
         
-     
 // 2 oth
@@ -2737,21 +2737,16 @@
         
-    
- 
 HystrixC
@@ -2884,21 +2884,16 @@
         
-     
 .withExe
@@ -3003,21 +3003,16 @@
         
-    
- 
 getIntPr
@@ -3102,16 +3102,24 @@
 t())));%0A
+        
 %0A       

Support RibbonCommand group key parameter