/*
 * Copyright 2015 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.registry;

import net.uncontended.precipice.Service;
import net.uncontended.precipice.SuperStatusInterface;
import net.uncontended.precipice.metrics.*;

import java.util.concurrent.TimeUnit;

public class Summary<T extends Enum<T> & SuperStatusInterface> {
    private final long period;
    private final TimeUnit unit;
    private final ActionMetrics<T> actionMetrics;
    private final Service service;

    public long pendingCount = 0;
    public long remainingCapacity = 0;

    public final long[] metricCounts;

    public long totalSuccesses = 0;
    public long totalErrors = 0;
    public long totalTimeouts = 0;
    public long totalMaxConcurrency = 0;
    public long totalQueueFull = 0;
    public long totalCircuitOpen = 0;
    public long totalAllRejected = 0;
    public long successes = 0;
    public long errors = 0;
    public long timeouts = 0;
    public long maxConcurrency = 0;
    public long queueFull = 0;
    public long circuitOpen = 0;
    public long allRejected = 0;
    public LatencySnapshot successLatency = LatencyMetrics.DEFAULT_SNAPSHOT;
    public LatencySnapshot errorLatency = LatencyMetrics.DEFAULT_SNAPSHOT;
    public LatencySnapshot timeoutLatency = LatencyMetrics.DEFAULT_SNAPSHOT;

    public LatencySnapshot totalSuccessLatency = LatencyMetrics.DEFAULT_SNAPSHOT;
    public LatencySnapshot totalErrorLatency = LatencyMetrics.DEFAULT_SNAPSHOT;
    public LatencySnapshot totalTimeoutLatency = LatencyMetrics.DEFAULT_SNAPSHOT;

    Summary(long period, TimeUnit unit, ActionMetrics<T> metrics, Service service) {
        this.period = period;
        this.unit = unit;
        actionMetrics = metrics;
        this.service = service;
        remainingCapacity = service.remainingCapacity();
        metricCounts = new long[metrics.getMetricType().getEnumConstants().length];
    }

    public void refresh() {
        pendingCount = service.pendingCount();
        remainingCapacity = service.remainingCapacity();

        MetricCounter<T> metricCounter = actionMetrics.totalCountMetricCounter();

//        totalSuccesses = metricCounter.getMetricCount(Metric.SUCCESS);
//        totalErrors = metricCounter.getMetricCount(Metric.ERROR);
//        totalTimeouts = metricCounter.getMetricCount(Metric.TIMEOUT);
//        totalMaxConcurrency = metricCounter.getMetricCount(Metric.MAX_CONCURRENCY_LEVEL_EXCEEDED);
//        totalQueueFull = metricCounter.getMetricCount(Metric.QUEUE_FULL);
//        totalCircuitOpen = metricCounter.getMetricCount(Metric.CIRCUIT_OPEN);
//        totalAllRejected = metricCounter.getMetricCount(Metric.ALL_SERVICES_REJECTED);
        successes = 0;
        errors = 0;
        timeouts = 0;
        maxConcurrency = 0;
        queueFull = 0;
        circuitOpen = 0;
        allRejected = 0;

        for (MetricCounter<T> m : actionMetrics.metricCounterIterable(period, unit)) {
//            successes += m.getMetricCount(Metric.SUCCESS);
//            errors += m.getMetricCount(Metric.ERROR);
//            timeouts += m.getMetricCount(Metric.TIMEOUT);
//            maxConcurrency += m.getMetricCount(Metric.MAX_CONCURRENCY_LEVEL_EXCEEDED);
//            queueFull += m.getMetricCount(Metric.QUEUE_FULL);
//            circuitOpen += m.getMetricCount(Metric.CIRCUIT_OPEN);
//            allRejected += m.getMetricCount(Metric.ALL_SERVICES_REJECTED);
        }

        LatencyMetrics latencyMetrics = service.getLatencyMetrics();
        if (latencyMetrics instanceof IntervalLatencyMetrics) {
            IntervalLatencyMetrics intervalMetrics = (IntervalLatencyMetrics) latencyMetrics;
//            successLatency = intervalMetrics.intervalSnapshot(Metric.SUCCESS);
//            errorLatency = intervalMetrics.intervalSnapshot(Metric.ERROR);
//            timeoutLatency = intervalMetrics.intervalSnapshot(Metric.TIMEOUT);
        }

//        totalSuccessLatency = latencyMetrics.latencySnapshot(Metric.SUCCESS);
//        totalErrorLatency = latencyMetrics.latencySnapshot(Metric.ERROR);
//        totalTimeoutLatency = latencyMetrics.latencySnapshot(Metric.TIMEOUT);
    }
}

@@ -1139,501 +1139,69 @@
 g%5B%5D 
-metricCounts;%0A%0A    public long totalSuccesses = 0;%0A    public long totalErrors = 0;%0A    public long totalTimeouts = 0;%0A    public long totalMaxConcurrency = 0;%0A    public long totalQueueFull = 0;%0A    public long totalCircuitOpen = 0;%0A    public long totalAllRejected = 0;%0A    public long successes = 0;%0A    public long errors = 0;%0A    public long timeouts = 0;%0A    public long maxConcurrency = 0;%0A    public long queueFull = 0;%0A    public long circuitOpen = 0;%0A    public long allRejected = 0;
+totalMetricCounts;%0A    public final long%5B%5D metricCounts;%0A    
 %0A   
@@ -1666,24 +1666,63 @@
 LT_SNAPSHOT;
+%0A    private final Class%3CT%3E metricType;
 %0A%0A    Summar
@@ -1864,31 +1864,30 @@
     
-actionMetrics = metrics
+this.service = service
 ;%0A  
@@ -1892,38 +1892,39 @@
         
-this.service = service
+actionMetrics = metrics
 ;%0A      
@@ -1984,24 +1984,146 @@
       metric
+Type = metrics.getMetricType();%0A        totalMetricCounts = new long%5BmetricType.getEnumConstants().length%5D;%0A        metric
 Counts = new
@@ -2129,27 +2129,16 @@
 w long%5Bm
-etrics.getM
 etricTyp
@@ -2138,18 +2138,16 @@
 tricType
-()
 .getEnum
@@ -2328,25 +2328,30 @@
 cCounter%3CT%3E 
-m
+totalM
 etricCounter
@@ -2395,26 +2395,24 @@
 ter();%0A%0A
-//
         
 totalSuc
@@ -2407,322 +2407,103 @@
     
-totalSuccesses = metricCounter.getMetricCount(Metric.SUCCESS);%0A//        totalErrors = metricCounter.getMetricCount(Metric.ERROR);%0A//        totalTimeouts = metricCounter.getMetricCount(Metric.TIMEOUT);%0A//        totalMaxConcurrency = metricCounter.getMetricCount(Metric.MAX_CONCURRENCY_LEVEL_EXCEEDED
+for (T t : metricType.getEnumConstants()) %7B%0A            int metricIndex = t.ordinal(
 );%0A
-//
         
 tota
@@ -2502,408 +2502,135 @@
     
-totalQueueFull = metricCounter.getMetricCount(Metric.QUEUE_FULL);%0A//        totalCircuitOpen = metricCounter.getMetricCount(Metric.CIRCUIT_OPEN);%0A//        totalAllRejected = metricCounter.getMetricCount(Metric.ALL_SERVICES_REJECTED);%0A        successes = 0;%0A        errors = 0;%0A        timeouts = 0;%0A        maxConcurrency = 0;%0A        queueFull = 0;%0A        circuitOpen = 0;%0A        allRejected = 0;
+    metricCounts%5BmetricIndex%5D = 0;%0A            totalMetricCounts%5BmetricIndex%5D = totalMetricCounter.getMetricCount(t);%0A        %7D
 %0A%0A  
@@ -2714,18 +2714,16 @@
 nit)) %7B%0A
-//
         
@@ -2730,349 +2730,93 @@
     
-successes += m.getMetricCount(Metric.SUCCESS);%0A//            errors += m.getMetricCount(Metric.ERROR);%0A//            timeouts += m.getMetricCount(Metric.TIMEOUT);%0A//            maxConcurrency += m.getMetricCount(Metric.MAX_CONCURRENCY_LEVEL_EXCEEDED);%0A//            queueFull += m.getMetricCount(Metric.QUEUE_FULL);%0A//            circuitOpen
+for (T t : metricType.getEnumConstants()) %7B%0A                metricCounts%5Bt.ordinal()%5D
  += 
@@ -2836,32 +2836,12 @@
 unt(
-Metric.CIRCUIT_OPEN
+t
 );%0A
-//
     
@@ -2852,70 +2852,9 @@
     
-allRejected += m.getMetricCount(Metric.ALL_SERVICES_REJECTED);
+%7D
 %0A   

Update summary for new statuses