package de.ahus1.hystrix.util;

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

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.netflix.hystrix.util.HystrixRollingNumberEvent;
import com.quigley.zabbixj.metrics.MetricsException;
import com.quigley.zabbixj.metrics.MetricsKey;
import com.quigley.zabbixj.metrics.MetricsProvider;

public class ZabbixCommandMetricsProvider implements MetricsProvider {

    private static Logger LOG = LoggerFactory
            .getLogger(ZabbixCommandMetricsProvider.class);

    Map<String, HystrixRollingNumberEvent> numberEvents = new HashMap<>();
    {
        numberEvents.put("CollapsedRequests",
                HystrixRollingNumberEvent.COLLAPSED);
        numberEvents.put("ExceptionsThrown",
                HystrixRollingNumberEvent.EXCEPTION_THROWN);
        numberEvents.put("Failure", HystrixRollingNumberEvent.FAILURE);
        numberEvents.put("FallbackFailure",
                HystrixRollingNumberEvent.FALLBACK_FAILURE);
        numberEvents.put("FallbackRejection",
                HystrixRollingNumberEvent.FALLBACK_REJECTION);
        numberEvents.put("FallbackSuccess",
                HystrixRollingNumberEvent.FALLBACK_SUCCESS);
        numberEvents.put("ResponsesFromCache",
                HystrixRollingNumberEvent.RESPONSE_FROM_CACHE);
        numberEvents.put("SemaphoreRejected",
                HystrixRollingNumberEvent.SEMAPHORE_REJECTED);
        numberEvents.put("ShortCircuited",
                HystrixRollingNumberEvent.SHORT_CIRCUITED);
        numberEvents.put("Success", HystrixRollingNumberEvent.SUCCESS);
        numberEvents.put("ThreadPoolRejected",
                HystrixRollingNumberEvent.THREAD_POOL_REJECTED);
        numberEvents.put("Timeout", HystrixRollingNumberEvent.TIMEOUT);
    }

    Map<String, HystrixZabbixMetricsPublisherCommand> map = new HashMap<>();

    @Override
    public Object getValue(MetricsKey key) throws MetricsException {
        if (key.getKey().equals("discovery")) {
            try {
                JSONObject discovery = new JSONObject();
                JSONArray array = new JSONArray();
                discovery.put("data", array);
                for (String command : map.keySet()) {
                    JSONObject element = new JSONObject();
                    element.put("{#COMMAND}", command);
                    array.put(element);
                }
                LOG.info("discovery: {}", discovery);
                return discovery;
            } catch (JSONException e) {
                throw new MetricsException(e);
            }
        } else if (key.getKey().startsWith("count")) {
            HystrixRollingNumberEvent event = numberEvents.get(key.getKey()
                    .replaceFirst("count", ""));
            if (event == null) {
                throw new MetricsException("unknown key " + key);
            }
            HystrixZabbixMetricsPublisherCommand command = map.get(key
                    .getParameters()[0]);
            if (command == null) {
                throw new MetricsException("unknown command referenced in "
                        + key);
            }
            return command.getMetrics().getCumulativeCount(event);
        } else if (key.getKey().equals("latencyExecute")) {
            HystrixZabbixMetricsPublisherCommand command = map.get(key
                    .getParameters()[0]);
            if (command == null) {
                throw new MetricsException("unknown command referenced in "
                        + key);
            }
            String percentile = key.getParameters()[1];
            if (percentile.equalsIgnoreCase("mean")) {
                return command.getMetrics().getTotalTimeMean();
            } else {
                return command.getMetrics().getTotalTimePercentile(
                        Double.parseDouble(percentile));
            }
        } else if (key.getKey().equals("latencyTotal")) {
            HystrixZabbixMetricsPublisherCommand command = map.get(key
                    .getParameters()[0]);
            if (command == null) {
                throw new MetricsException("unknown command referenced in "
                        + key);
            }
            String percentile = key.getParameters()[1];
            if (percentile.equalsIgnoreCase("mean")) {
                return command.getMetrics().getTotalTimeMean();
            } else {
                return command.getMetrics().getTotalTimePercentile(
                        Double.parseDouble(percentile));
            }
        } else if (key.getKey().equals("latencyExecute")) {
            HystrixZabbixMetricsPublisherCommand command = map.get(key
                    .getParameters()[0]);
            if (command == null) {
                throw new MetricsException("unknown command referenced in "
                        + key);
            }
            String percentile = key.getParameters()[1];
            if (percentile.equalsIgnoreCase("mean")) {
                return command.getMetrics().getExecutionTimeMean();
            } else {
                return command.getMetrics().getExecutionTimePercentile(
                        Double.parseDouble(percentile));
            }
        } else {
            throw new MetricsException("unknown key " + key);
        }
    }

    public void register(HystrixZabbixMetricsPublisherCommand command) {
        map.put(command.getKey().name(), command);
    }
}

@@ -1947,24 +1947,211 @@
 shMap%3C%3E();%0A%0A
+    /**%0A     * Return a metric for a given key. If the command is unknown, return 0 as a%0A     * neutral value, as Hystrix will register them only at the first command%0A     * run.%0A     */%0A
     @Overrid
@@ -2957,16 +2957,36 @@
  event =
+%0A                   
  numberE
@@ -3007,37 +3007,16 @@
 getKey()
-%0A                    
 .replace
@@ -3203,36 +3203,24 @@
 nd command =
- map.get(key
 %0A           
@@ -3220,32 +3220,43 @@
                 
+map.get(key
 .getParameters()
@@ -3316,98 +3316,16 @@
     
-throw new MetricsException(%22unknown command referenced in %22%0A                        + key)
+return 0
 ;%0A  
@@ -3517,36 +3517,24 @@
 nd command =
- map.get(key
 %0A           
@@ -3534,32 +3534,43 @@
                 
+map.get(key
 .getParameters()
@@ -3630,98 +3630,16 @@
     
-throw new MetricsException(%22unknown command referenced in %22%0A                        + key)
+return 0
 ;%0A  
@@ -4097,36 +4097,24 @@
 nd command =
- map.get(key
 %0A           
@@ -4114,32 +4114,43 @@
                 
+map.get(key
 .getParameters()
@@ -4210,98 +4210,16 @@
     
-throw new MetricsException(%22unknown command referenced in %22%0A                        + key)
+return 0
 ;%0A  
@@ -4683,28 +4683,16 @@
 ommand =
- map.get(key
 %0A       
@@ -4700,24 +4700,35 @@
             
+map.get(key
 .getParamete
@@ -4792,98 +4792,16 @@
     
-throw new MetricsException(%22unknown command referenced in %22%0A                        + key)
+return 0
 ;%0A  

return 0 for any yet unknown metric