/*
 * #%L
 * servo-core
 * %%
 * Copyright (C) 2011 - 2012 Netflix
 * %%
 * 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.
 * #L%
 */
package com.netflix.servo.util;

import com.google.common.base.Objects;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import com.google.common.collect.MapMaker;

import com.netflix.servo.BasicTagList;
import com.netflix.servo.TagList;
import com.netflix.servo.DefaultMonitorRegistry;
import com.netflix.servo.publish.MetricConfig;
import com.netflix.servo.annotations.DataSourceType;
import com.netflix.servo.annotations.Monitor;
import com.netflix.servo.annotations.MonitorId;
import com.netflix.servo.annotations.MonitorTags;

import java.util.Map;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.atomic.AtomicInteger;

public class Counters {

    private static final LoadingCache<MetricConfig,BasicCounter> COUNTERS =
        CacheBuilder.newBuilder().build(
        new CacheLoader<MetricConfig,BasicCounter>() {
            @Override
            public BasicCounter load(MetricConfig key) {
                BasicCounter counter = new BasicCounter(key);
                DefaultMonitorRegistry.getInstance().registerObject(counter);
                return counter;
            }
        });

    private static final ThreadLocal<TagList> CONTEXT =
        new ThreadLocal<TagList>();

    private Counters() {
    }

    private static void setTags(TagList tags) {
        CONTEXT.set(tags);
    }

    private static TagList getTags() {
        return CONTEXT.get();
    }

    public static void increment(String name) {
        increment(new MetricConfig(name), 1);
    }

    public static void increment(String name, int delta) {
        increment(new MetricConfig(name), delta);
    }

    public static void increment(String name, TagList tags) {
        increment(new MetricConfig(name, tags), 1);
    }

    public static void increment(String name, TagList tags, int delta) {
        increment(new MetricConfig(name, tags), delta);
    }

    public static void increment(MetricConfig config, int delta) {
        TagList cxtTags = getTags();
        if (cxtTags != null) {
            String name = config.getName();
            TagList newTags = BasicTagList.concat(config.getTags(), cxtTags);
            MetricConfig newConfig = new MetricConfig(name, newTags);
            COUNTERS.getUnchecked(newConfig).increment(delta);
        } else {
            COUNTERS.getUnchecked(config).increment(delta);
        }
    }
}

@@ -1859,271 +1859,20 @@
 ate 
-static final ThreadLocal%3CTagList%3E CONTEXT =%0A        new ThreadLocal%3CTagList%3E();%0A%0A    private Counters() %7B%0A    %7D%0A%0A    private static void setTags(TagList tags) %7B%0A        CONTEXT.set(tags);%0A    %7D%0A%0A    private static TagList getTags() %7B%0A        return CONTEXT.get();
+Counters() %7B
 %0A   
@@ -2442,16 +2442,31 @@
 tTags = 
+TaggingContext.
 getTags(
@@ -2823,32 +2823,32 @@
 crement(delta);%0A
-
         %7D%0A    %7D%0A
@@ -2846,11 +2846,85 @@
  %7D%0A    %7D
+%0A%0A    public static void reset() %7B%0A        COUNTERS.invalidateAll();%0A    %7D
 %0A%7D%0A

use TaggingContext