/*
 * Copyright 2016 Open Networking Laboratory
 *
 * 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 org.onosproject.store.primitives.impl;

import java.util.Collection;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.function.BiFunction;
import java.util.function.Function;
import java.util.function.Predicate;

import org.onosproject.store.service.AsyncConsistentMap;
import org.onosproject.store.service.MapEvent;
import org.onosproject.store.service.MapEventListener;
import org.onosproject.store.service.Versioned;

import com.google.common.base.Throwables;
import com.google.common.collect.Maps;

/**
 * {@link AsyncConsistentMap} that meters all its operations.
 *
 * @param <K> key type
 * @param <V> value type
 */
public class MeteredAsyncConsistentMap<K, V>  extends DelegatingAsyncConsistentMap<K, V> {

    private static final String PRIMITIVE_NAME = "consistentMap";
    private static final String SIZE = "size";
    private static final String IS_EMPTY = "isEmpty";
    private static final String CONTAINS_KEY = "containsKey";
    private static final String CONTAINS_VALUE = "containsValue";
    private static final String GET = "get";
    private static final String COMPUTE_IF = "computeIf";
    private static final String PUT = "put";
    private static final String PUT_AND_GET = "putAndGet";
    private static final String PUT_IF_ABSENT = "putIfAbsent";
    private static final String REMOVE = "remove";
    private static final String CLEAR = "clear";
    private static final String KEY_SET = "keySet";
    private static final String VALUES = "values";
    private static final String ENTRY_SET = "entrySet";
    private static final String REPLACE = "replace";
    private static final String COMPUTE_IF_ABSENT = "computeIfAbsent";
    private static final String ADD_LISTENER = "addListener";
    private static final String REMOVE_LISTENER = "removeListener";
    private static final String NOTIFY_LISTENER = "notifyListener";

    private final Map<MapEventListener<K, V>, InternalMeteredMapEventListener> listeners =
            Maps.newIdentityHashMap();
    private final MeteringAgent monitor;

    public MeteredAsyncConsistentMap(AsyncConsistentMap<K, V> backingMap) {
        super(backingMap);
        this.monitor = new MeteringAgent(PRIMITIVE_NAME, backingMap.name(), true);
    }

    @Override
    public CompletableFuture<Integer> size() {
        final MeteringAgent.Context timer = monitor.startTimer(SIZE);
        return super.size()
                    .whenComplete((r, e) -> timer.stop(e));
    }

    @Override
    public CompletableFuture<Boolean> isEmpty() {
        final MeteringAgent.Context timer = monitor.startTimer(IS_EMPTY);
        return super.isEmpty()
                    .whenComplete((r, e) -> timer.stop(e));
    }

    @Override
    public CompletableFuture<Boolean> containsKey(K key) {
        final MeteringAgent.Context timer = monitor.startTimer(CONTAINS_KEY);
        return super.containsKey(key)
                    .whenComplete((r, e) -> timer.stop(e));
    }

    @Override
    public CompletableFuture<Boolean> containsValue(V value) {
        final MeteringAgent.Context timer = monitor.startTimer(CONTAINS_VALUE);
        return super.containsValue(value)
                    .whenComplete((r, e) -> timer.stop(e));
    }

    @Override
    public CompletableFuture<Versioned<V>> get(K key) {
        final MeteringAgent.Context timer = monitor.startTimer(GET);
        return super.get(key)
                    .whenComplete((r, e) -> timer.stop(e));
    }

    @Override
    public CompletableFuture<Versioned<V>> computeIfAbsent(K key,
                                                           Function<? super K, ? extends V> mappingFunction) {
        final MeteringAgent.Context timer = monitor.startTimer(COMPUTE_IF_ABSENT);
        return super.computeIfAbsent(key, mappingFunction)
                    .whenComplete((r, e) -> timer.stop(e));
    }

    @Override
    public CompletableFuture<Versioned<V>> computeIf(K key,
                                                     Predicate<? super V> condition,
                                                     BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
        final MeteringAgent.Context timer = monitor.startTimer(COMPUTE_IF);
        return super.computeIf(key, condition, remappingFunction)
                    .whenComplete((r, e) -> timer.stop(e));
    }

    @Override
    public CompletableFuture<Versioned<V>> put(K key, V value) {
        final MeteringAgent.Context timer = monitor.startTimer(PUT);
        return super.put(key, value)
                    .whenComplete((r, e) -> timer.stop(e));
    }

    @Override
    public CompletableFuture<Versioned<V>> putAndGet(K key, V value) {
        final MeteringAgent.Context timer = monitor.startTimer(PUT_AND_GET);
        return super.putAndGet(key, value)
                    .whenComplete((r, e) -> timer.stop(e));
    }

    @Override
    public CompletableFuture<Versioned<V>> remove(K key) {
        final MeteringAgent.Context timer = monitor.startTimer(REMOVE);
        return super.remove(key)
                    .whenComplete((r, e) -> timer.stop(e));
    }

    @Override
    public CompletableFuture<Void> clear() {
        final MeteringAgent.Context timer = monitor.startTimer(CLEAR);
        return super.clear()
                    .whenComplete((r, e) -> timer.stop(e));
    }

    @Override
    public CompletableFuture<Set<K>> keySet() {
        final MeteringAgent.Context timer = monitor.startTimer(KEY_SET);
        return super.keySet()
                    .whenComplete((r, e) -> timer.stop(e));
    }

    @Override
    public CompletableFuture<Collection<Versioned<V>>> values() {
        final MeteringAgent.Context timer = monitor.startTimer(VALUES);
        return super.values()
                    .whenComplete((r, e) -> timer.stop(e));
    }

    @Override
    public CompletableFuture<Set<Entry<K, Versioned<V>>>> entrySet() {
        final MeteringAgent.Context timer = monitor.startTimer(ENTRY_SET);
        return super.entrySet()
                    .whenComplete((r, e) -> timer.stop(e));
    }

    @Override
    public CompletableFuture<Versioned<V>> putIfAbsent(K key, V value) {
        final MeteringAgent.Context timer = monitor.startTimer(PUT_IF_ABSENT);
        return super.putIfAbsent(key, value)
                    .whenComplete((r, e) -> timer.stop(e));
    }

    @Override
    public CompletableFuture<Boolean> remove(K key, V value) {
        final MeteringAgent.Context timer = monitor.startTimer(REMOVE);
        return super.remove(key, value)
                    .whenComplete((r, e) -> timer.stop(e));

    }

    @Override
    public CompletableFuture<Boolean> remove(K key, long version) {
        final MeteringAgent.Context timer = monitor.startTimer(REMOVE);
        return super.remove(key, version)
                    .whenComplete((r, e) -> timer.stop(e));
    }

    @Override
    public CompletableFuture<Versioned<V>> replace(K key, V value) {
        final MeteringAgent.Context timer = monitor.startTimer(REPLACE);
        return super.replace(key, value)
                    .whenComplete((r, e) -> timer.stop(e));
    }

    @Override
    public CompletableFuture<Boolean> replace(K key, V oldValue, V newValue) {
        final MeteringAgent.Context timer = monitor.startTimer(REPLACE);
        return super.replace(key, oldValue, newValue)
                    .whenComplete((r, e) -> timer.stop(e));
    }

    @Override
    public CompletableFuture<Boolean> replace(K key, long oldVersion, V newValue) {
        final MeteringAgent.Context timer = monitor.startTimer(REPLACE);
        return super.replace(key, oldVersion, newValue)
                    .whenComplete((r, e) -> timer.stop(e));
    }

    @Override
    public CompletableFuture<Void> addListener(MapEventListener<K, V> listener) {
        final MeteringAgent.Context timer = monitor.startTimer(ADD_LISTENER);
        synchronized (listeners) {
            InternalMeteredMapEventListener meteredListener =
                    listeners.computeIfAbsent(listener, k -> new InternalMeteredMapEventListener(listener));
            return super.addListener(meteredListener)
                        .whenComplete((r, e) -> timer.stop(e));
        }
    }

    @Override
    public CompletableFuture<Void> removeListener(MapEventListener<K, V> listener) {
        final MeteringAgent.Context timer = monitor.startTimer(REMOVE_LISTENER);
        InternalMeteredMapEventListener meteredListener = listeners.remove(listener);
        if (meteredListener != null) {
            return super.removeListener(listener)
                        .whenComplete((r, e) -> timer.stop(e));
        } else {
            timer.stop(null);
            return CompletableFuture.completedFuture(null);
        }
    }

    private class InternalMeteredMapEventListener implements MapEventListener<K, V> {

        private final MapEventListener<K, V> listener;

        InternalMeteredMapEventListener(MapEventListener<K, V> listener) {
            this.listener = listener;
        }

        @Override
        public void event(MapEvent<K, V> event) {
            final MeteringAgent.Context timer = monitor.startTimer(NOTIFY_LISTENER);
            try {
                listener.event(event);
                timer.stop(null);
            } catch (Exception e) {
                timer.stop(e);
                Throwables.propagate(e);
            }
        }
    }
}