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

import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.BiFunction;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;

import org.onosproject.store.primitives.ConsistentMapBackedJavaMap;

import com.google.common.base.Objects;

/**
 * Test implementation of the consistent map.
 */
public final class TestConsistentMap<K, V> extends ConsistentMapAdapter<K, V> {

    private final List<MapEventListener<K, V>> listeners;
    private final Map<K, Versioned<V>> map;
    private final String mapName;
    private final AtomicLong counter = new AtomicLong(0);

    private TestConsistentMap(String mapName) {
        map = new HashMap<>();
        listeners = new LinkedList<>();
        this.mapName = mapName;
    }

    private Versioned<V> version(V v) {
        return new Versioned<>(v, counter.incrementAndGet(), System.currentTimeMillis());
    }

    /**
     * Notify all listeners of an event.
     */
    private void notifyListeners(String mapName,
                                 K key, Versioned<V> newvalue, Versioned<V> oldValue) {
        MapEvent<K, V> event = new MapEvent<>(mapName, key, newvalue, oldValue);
        listeners.forEach(
                listener -> listener.event(event)
        );
    }

    @Override
    public int size() {
        return map.size();
    }

    @Override
    public boolean isEmpty() {
        return map.isEmpty();
    }

    @Override
    public boolean containsKey(K key) {
        return map.containsKey(key);
    }

    @Override
    public boolean containsValue(V value) {
        return map.containsValue(value);
    }

    @Override
    public Versioned<V> get(K key) {
        return map.get(key);
    }

    @Override
    public Versioned<V> computeIfAbsent(K key, Function<? super K, ? extends V> mappingFunction) {
        AtomicBoolean updated = new AtomicBoolean(false);
        Versioned<V> result = map.compute(key, (k, v) -> {
            if (v == null) {
                updated.set(true);
                return version(mappingFunction.apply(key));
            }
            return v;
        });
        if (updated.get()) {
            notifyListeners(mapName, key, result, null);
        }
        return result;
    }

    @Override
    public Versioned<V> compute(K key, BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
            AtomicBoolean updated = new AtomicBoolean(false);
            AtomicReference<Versioned<V>> previousValue = new AtomicReference<>();
            Versioned<V> result = map.compute(key, (k, v) -> {
                    updated.set(true);
                    previousValue.set(v);
                    return version(remappingFunction.apply(k, Versioned.valueOrNull(v)));
                });
            if (updated.get()) {
                notifyListeners(mapName, key, result, previousValue.get());
            }
            return result;
    }

    @Override
    public Versioned<V> computeIfPresent(K key, BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
        AtomicBoolean updated = new AtomicBoolean(false);
        AtomicReference<Versioned<V>> previousValue = new AtomicReference<>();
        Versioned<V> result = map.compute(key, (k, v) -> {
            if (v != null) {
                updated.set(true);
                previousValue.set(v);
                return version(remappingFunction.apply(k, v.value()));
            }
            return v;
        });
        if (updated.get()) {
            notifyListeners(mapName, key, result, previousValue.get());
        }
        return result;
    }

    @Override
    public Versioned<V> computeIf(K key, Predicate<? super V> condition,
                                  BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
        AtomicBoolean updated = new AtomicBoolean(false);
        AtomicReference<Versioned<V>> previousValue = new AtomicReference<>();
        Versioned<V> result = map.compute(key, (k, v) -> {
            if (condition.test(Versioned.valueOrNull(v))) {
                previousValue.set(v);
                updated.set(true);
                return version(remappingFunction.apply(k, Versioned.valueOrNull(v)));
            }
            return v;
        });
        if (updated.get()) {
            notifyListeners(mapName, key, result, previousValue.get());
        }
        return result;
    }

    @Override
    public Versioned<V> put(K key, V value) {
        Versioned<V> newValue = version(value);
        Versioned<V> previousValue = map.put(key, newValue);
        notifyListeners(mapName, key, newValue, previousValue);
        return previousValue;
    }

    @Override
    public Versioned<V> putAndGet(K key, V value) {
        Versioned<V> newValue = version(value);
        Versioned<V> previousValue = map.put(key, newValue);
        notifyListeners(mapName, key, newValue, previousValue);
        return newValue;
    }

    @Override
    public Versioned<V> remove(K key) {
        Versioned<V> result = map.remove(key);
        notifyListeners(mapName, key, null, result);
        return result;
    }

    @Override
    public void clear() {
        map.keySet().forEach(this::remove);
    }

    @Override
    public Set<K> keySet() {
        return map.keySet();
    }

    @Override
    public Collection<Versioned<V>> values() {
        return map.values()
                .stream()
                .collect(Collectors.toList());
    }

    @Override
    public Set<Map.Entry<K, Versioned<V>>> entrySet() {
        return map.entrySet();
    }

    @Override
    public Versioned<V> putIfAbsent(K key, V value) {
        Versioned<V> newValue = version(value);
        Versioned<V> result =  map.putIfAbsent(key, newValue);
        if (result == null) {
            notifyListeners(mapName, key, newValue, result);
        }
        return result;
    }

    @Override
    public boolean remove(K key, V value) {
        Versioned<V> existingValue = map.get(key);
        if (Objects.equal(Versioned.valueOrNull(existingValue), value)) {
            map.remove(key);
            notifyListeners(mapName, key, null, existingValue);
            return true;
        }
        return false;
    }

    @Override
    public boolean remove(K key, long version) {
        Versioned<V> existingValue = map.get(key);
        if (existingValue == null) {
            return false;
        }
        if (existingValue.version() == version) {
            map.remove(key);
            notifyListeners(mapName, key, null, existingValue);
            return true;
        }
        return false;
    }

    @Override
    public Versioned<V> replace(K key, V value) {
        Versioned<V> existingValue = map.get(key);
        if (existingValue == null) {
            return null;
        }
        Versioned<V> newValue = version(value);
        Versioned<V> result = map.put(key, newValue);
        notifyListeners(mapName, key, newValue, result);
        return result;
    }

    @Override
    public boolean replace(K key, V oldValue, V newValue) {
        Versioned<V> existingValue = map.get(key);
        if (existingValue == null || !existingValue.value().equals(oldValue)) {
            return false;
        }
        Versioned<V> value = version(newValue);
        Versioned<V> result = map.put(key, value);
        notifyListeners(mapName, key, value, result);
        return true;
    }

    @Override
    public boolean replace(K key, long oldVersion, V newValue) {
        Versioned<V> existingValue = map.get(key);
        if (existingValue == null || existingValue.version() != oldVersion) {
            return false;
        }
        Versioned<V> value = version(newValue);
        Versioned<V> result = map.put(key, value);
        notifyListeners(mapName, key, value, result);
        return true;
    }

    @Override
    public void addListener(MapEventListener<K, V> listener) {
        listeners.add(listener);
    }

    @Override
    public void removeListener(MapEventListener<K, V> listener) {
        listeners.remove(listener);
    }

    @Override
    public Map<K, V> asJavaMap() {
        return new ConsistentMapBackedJavaMap<>(this);
    }

    public static Builder builder() {
        return new Builder();
    }

    public static class Builder<K, V> extends ConsistentMapBuilder<K, V> {

        @Override
        public ConsistentMap<K, V> build() {
            return new TestConsistentMap<>(name());
        }

        @Override
        public AsyncConsistentMap<K, V> buildAsyncMap() {
            return null;
        }

    }

}
