/*
 * Copyright 2014 Timothy Brooks
 *
 * Licensed 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 net.uncontended.precipice.metrics;

import net.uncontended.precipice.concurrent.LongAdder;

public class Slot {

    private final LongAdder successes = new LongAdder();
    private final LongAdder errors = new LongAdder();
    private final LongAdder timeouts = new LongAdder();
    private final LongAdder circuitOpen = new LongAdder();
    private final LongAdder queueFull = new LongAdder();
    private final LongAdder maxConcurrencyExceeded = new LongAdder();
    private final long second;

    public Slot(long second) {
        this.second = second;
    }

    public void incrementMetric(Metric metric) {
        switch (metric) {
            case SUCCESS:
                successes.increment();
                break;
            case ERROR:
                errors.increment();
                break;
            case TIMEOUT:
                timeouts.increment();
                break;
            case CIRCUIT_OPEN:
                circuitOpen.increment();
                break;
            case QUEUE_FULL:
                queueFull.increment();
                break;
            case MAX_CONCURRENCY_LEVEL_EXCEEDED:
                maxConcurrencyExceeded.increment();
                break;
            default:
                throw new RuntimeException("Unknown metric: " + metric);
        }
    }

    public LongAdder getMetric(Metric metric) {
        switch (metric) {
            case SUCCESS:
                return successes;
            case ERROR:
                return errors;
            case TIMEOUT:
                return timeouts;
            case CIRCUIT_OPEN:
                return circuitOpen;
            case QUEUE_FULL:
                return queueFull;
            case MAX_CONCURRENCY_LEVEL_EXCEEDED:
                return maxConcurrencyExceeded;
            default:
                throw new RuntimeException("Unknown metric: " + metric);
        }
    }

    public long getAbsoluteSlot() {
        return second;
    }

    @Override
    public String toString() {
        return "Slot{" +
                "successes=" + successes +
                ", errors=" + errors +
                ", timeouts=" + timeouts +
                ", circuitOpen=" + circuitOpen +
                ", queueFull=" + queueFull +
                ", maxConcurrencyExceeded=" + maxConcurrencyExceeded +
                ", second=" + second +
                '}';
    }
}

@@ -695,310 +695,92 @@
 r;%0A%0A
-public class Slot %7B%0A%0A    private final LongAdder successes = new LongAdder();%0A    private final LongAdder errors = new LongAdder();%0A    private final LongAdder timeouts = new LongAdder();%0A    private final LongAdder circuitOpen = new LongAdder();%0A    private final LongAdder queueFull = new LongAdder()
+import java.util.Arrays;%0A%0Apublic class Slot %7B%0A%0A    private final LongAdder%5B%5D metrics
 ;%0A  
@@ -799,89 +799,25 @@
 nal 
-LongAdder maxConcurrencyExceeded = new LongAdder();%0A    private final long second
+long absoluteSlot
 ;%0A%0A 
@@ -836,22 +836,28 @@
 ot(long 
-second
+absoluteSlot
 ) %7B%0A    
@@ -869,180 +869,95 @@
 his.
-second = second
+absoluteSlot = absoluteSlot
 ;%0A    
-%7D%0A%0A
     
-public void incrementMetric(Metric metric) %7B%0A        switch (metric) %7B%0A            case SUCCESS:%0A                successes.increment
+Metric%5B%5D metricValues = Metric.values
 ();%0A
+%0A
         
     
@@ -956,594 +956,153 @@
     
-        break;%0A            case ERROR:%0A                errors.increment();%0A                break;%0A            case TIMEOUT:%0A                timeouts.increment();%0A                break;%0A            case CIRCUIT_OPEN:%0A                circuitOpen.increment();%0A                break;%0A            case QUEUE_FULL:%0A                queueFull.increment();%0A                break;%0A            case MAX_CONCURRENCY_LEVEL_EXCEEDED:%0A                maxConcurrencyExceeded.increment();%0A                break;%0A            default:%0A                throw new RuntimeException(%22Unknown metric: %22 + metric
+metrics = new LongAdder%5BmetricValues.length%5D;%0A        for (Metric metric : metricValues) %7B%0A            metrics%5Bmetric.ordinal()%5D = new LongAdder(
 );%0A 
@@ -1132,20 +1132,21 @@
 lic 
-LongAdder ge
+void incremen
 tMet
@@ -1178,394 +1178,110 @@
     
-switch (metric) %7B%0A            case SUCCESS:%0A                return successes;%0A            case ERROR:%0A                return errors;%0A            case TIMEOUT:%0A                return timeouts;%0A            case CIRCUIT_OPEN:%0A                return circuitOpen;%0A            case QUEUE_FULL:%0A                return queueFull;%0A            case MAX_CONCURRENCY_LEVEL_EXCEEDED:%0A       
+metrics%5Bmetric.ordinal()%5D.increment();%0A    %7D%0A%0A    public LongAdder getMetric(Metric metric) %7B%0A
         
  ret
@@ -1280,17 +1280,16 @@
     
- 
 return m
 axCo
@@ -1288,134 +1288,33 @@
 rn m
-axConcurrencyExceeded;%0A            default:%0A                throw new RuntimeException(%22Unknown metric: %22 + metric);%0A        %7D
+etrics%5Bmetric.ordinal()%5D;
 %0A   
@@ -1368,22 +1368,28 @@
  return 
-second
+absoluteSlot
 ;%0A    %7D%0A
@@ -1480,317 +1480,95 @@
    %22
-successes=%22 + successes +%0A                %22, error
+metric
 s=%22 + 
-errors +%0A                %22, timeouts=%22 + timeouts +%0A                %22, circuitOpen=%22 + circuitOpen +%0A                %22, queueFull=%22 + queueFull +%0A                %22, maxConcurrencyExceeded=%22 + maxConcurrencyExceeded +%0A                %22, second=%22 + second
+Arrays.toString(metrics) +%0A                %22, absoluteSlot=%22 + absoluteSlot
  +%0A 

Refactor slot