/*
 * 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 static com.google.common.base.Preconditions.checkNotNull;

import java.util.Map;
import java.util.concurrent.CompletableFuture;

import org.onosproject.store.service.AsyncAtomicValue;
import org.onosproject.store.service.AsyncConsistentMap;
import org.onosproject.store.service.AtomicValueEvent;
import org.onosproject.store.service.AtomicValueEventListener;
import org.onosproject.store.service.MapEvent;
import org.onosproject.store.service.MapEventListener;
import org.onosproject.store.service.Serializer;
import org.onosproject.store.service.Versioned;

import com.google.common.base.Throwables;
import com.google.common.collect.Maps;
import org.onosproject.utils.MeteringAgent;


public class DefaultAsyncAtomicValue<V> implements AsyncAtomicValue<V> {

    private final String name;
    private final Serializer serializer;
    private final AsyncConsistentMap<String, byte[]> backingMap;
    private final Map<AtomicValueEventListener<V>, MapEventListener<String, byte[]>> listeners =
            Maps.newIdentityHashMap();
    private final MeteringAgent monitor;

    private static final String COMPONENT_NAME = "atomicValue";
    private static final String GET = "get";
    private static final String GET_AND_SET = "getAndSet";
    private static final String SET = "set";
    private static final String COMPARE_AND_SET = "compareAndSet";
    private static final String ADD_LISTENER = "addListener";
    private static final String REMOVE_LISTENER = "removeListener";
    private static final String NOTIFY_LISTENER = "notifyListener";

    public DefaultAsyncAtomicValue(String name, Serializer serializer, AsyncConsistentMap<String, byte[]> backingMap) {
        this.name = checkNotNull(name, "name must not be null");
        this.serializer = checkNotNull(serializer, "serializer must not be null");
        this.backingMap = checkNotNull(backingMap, "backingMap must not be null");
        this.monitor = new MeteringAgent(COMPONENT_NAME, name, true);
    }

    @Override
    public String name() {
        return name;
    }

    @Override
    public CompletableFuture<Boolean> compareAndSet(V expect, V update) {
        final MeteringAgent.Context newTimer = monitor.startTimer(COMPARE_AND_SET);
        return backingMap.replace(name, serializer.encode(expect), serializer.encode(update))
                         .whenComplete((r, e) -> newTimer.stop(e));
    }

    @Override
    public CompletableFuture<V> get() {
        final MeteringAgent.Context newTimer = monitor.startTimer(GET);
        return backingMap.get(name)
                         .thenApply(Versioned::valueOrNull)
                         .thenApply(v -> v == null ? null : serializer.<V>decode(v))
                         .whenComplete((r, e) -> newTimer.stop(e));
    }

    @Override
    public CompletableFuture<V> getAndSet(V value) {
        final MeteringAgent.Context newTimer = monitor.startTimer(GET_AND_SET);
        if (value == null) {
            return backingMap.remove(name)
                             .thenApply(Versioned::valueOrNull)
                             .thenApply(v -> v == null ? null : serializer.<V>decode(v))
                             .whenComplete((r, e) -> newTimer.stop(e));
        }
        return backingMap.put(name, serializer.encode(value))
                         .thenApply(Versioned::valueOrNull)
                         .thenApply(v -> v == null ? null : serializer.<V>decode(v))
                         .whenComplete((r, e) -> newTimer.stop(e));
    }

    @Override
    public CompletableFuture<Void> set(V value) {
        final MeteringAgent.Context newTimer = monitor.startTimer(SET);
        if (value == null) {
            return backingMap.remove(name)
                             .whenComplete((r, e) -> newTimer.stop(e))
                             .thenApply(v -> null);

        }
        return backingMap.put(name, serializer.encode(value))
                         .whenComplete((r, e) -> newTimer.stop(e))
                         .thenApply(v -> null);
    }

    @Override
    public CompletableFuture<Void> addListener(AtomicValueEventListener<V> listener) {
        checkNotNull(listener, "listener must not be null");
        final MeteringAgent.Context newTimer = monitor.startTimer(ADD_LISTENER);
        MapEventListener<String, byte[]> mapListener =
                listeners.computeIfAbsent(listener, key -> new InternalMapValueEventListener(listener));
        return backingMap.addListener(mapListener).whenComplete((r, e) -> newTimer.stop(e));
    }

    @Override
    public CompletableFuture<Void> removeListener(AtomicValueEventListener<V> listener) {
        checkNotNull(listener, "listener must not be null");
        final MeteringAgent.Context newTimer = monitor.startTimer(REMOVE_LISTENER);
        MapEventListener<String, byte[]> mapListener = listeners.remove(listener);
        if (mapListener != null) {
            return backingMap.removeListener(mapListener)
                             .whenComplete((r, e) -> newTimer.stop(e));
        } else {
            newTimer.stop(null);
            return CompletableFuture.completedFuture(null);
        }
    }

    private class InternalMapValueEventListener implements MapEventListener<String, byte[]> {

        private final AtomicValueEventListener<V> listener;

        InternalMapValueEventListener(AtomicValueEventListener<V> listener) {
            this.listener = listener;
        }

        @Override
        public void event(MapEvent<String, byte[]> event) {
            if (event.key().equals(name)) {
                final MeteringAgent.Context newTimer = monitor.startTimer(NOTIFY_LISTENER);
                byte[] rawNewValue = Versioned.valueOrNull(event.newValue());
                byte[] rawOldValue = Versioned.valueOrNull(event.oldValue());
                try {
                    listener.event(new AtomicValueEvent<>(name,
                            rawNewValue == null ? null : serializer.decode(rawNewValue),
                                    rawOldValue == null ? null : serializer.decode(rawOldValue)));
                    newTimer.stop(null);
                } catch (Exception e) {
                    newTimer.stop(e);
                    Throwables.propagate(e);
                }
            }
        }
    }
}