/*
 * 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.AtomicLong;
import java.util.function.BiFunction;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;

import org.onosproject.core.ApplicationId;
import static org.onosproject.store.service.MapEvent.Type;
import static org.onosproject.store.service.MapEvent.Type.*;

/**
 * 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 HashMap<K, 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, Type type,
                                 K key, Versioned<V> value) {
        MapEvent<K, V> event = new MapEvent<>(mapName, type, key, value);
        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) {
        V value = map.get(key);
        if (value != null) {
            return version(value);
        } else {
            return null;
        }
    }

    @Override
    public Versioned<V> computeIfAbsent(K key, Function<? super K, ? extends V> mappingFunction) {
        Versioned<V> result = version(map.computeIfAbsent(key, mappingFunction));
        notifyListeners(mapName, INSERT, key, result);
        return result;
    }

    @Override
    public Versioned<V> compute(K key, BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
        return version(map.compute(key, remappingFunction));
    }

    @Override
    public Versioned<V> computeIfPresent(K key, BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
        return version(map.computeIfPresent(key, remappingFunction));
    }

    @Override
    public Versioned<V> computeIf(K key, Predicate<? super V> condition,
                                  BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
        return null;
    }

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

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

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

    @Override
    public void clear() {
        map.clear();
    }

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

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

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

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

    @Override
    public boolean remove(K key, V value) {
        boolean removed = map.remove(key, value);
        if (removed) {
            notifyListeners(mapName, REMOVE, key, null);
        }
        return removed;
    }

    @Override
    public boolean remove(K key, long version) {
        boolean removed =  map.remove(key, version);
        if (removed) {
            notifyListeners(mapName, REMOVE, key, null);
        }
        return removed;
    }

    @Override
    public boolean replace(K key, V oldValue, V newValue) {
        boolean replaced = map.replace(key, oldValue, newValue);
        if (replaced) {
            notifyListeners(mapName, REMOVE, key, null);
        }
        return replaced;
    }

    @Override
    public boolean replace(K key, long oldVersion, V newValue) {
        boolean replaced =  map.replace(key, map.get(key), newValue);
        if (replaced) {
            notifyListeners(mapName, REMOVE, key, null);
        }
        return replaced;
    }

    @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 map;
    }

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

    public static class Builder<K, V> implements ConsistentMapBuilder<K, V> {
        String mapName = "map";

        @Override
        public ConsistentMapBuilder<K, V> withName(String mapName) {
            this.mapName = mapName;
            return this;
        }

        @Override
        public ConsistentMapBuilder<K, V> withApplicationId(ApplicationId id) {
            return this;
        }

        @Override
        public ConsistentMapBuilder<K, V> withSerializer(Serializer serializer) {
            return this;
        }

        @Override
        public ConsistentMapBuilder<K, V> withPartitionsDisabled() {
            return this;
        }

        @Override
        public ConsistentMapBuilder<K, V> withUpdatesDisabled() {
            return this;
        }

        @Override
        public ConsistentMapBuilder<K, V> withPurgeOnUninstall() {
            return this;
        }

        @Override
        public ConsistentMapBuilder<K, V> withRelaxedReadConsistency() {
            return this;
        }

        @Override
        public ConsistentMapBuilder<K, V> withMeteringDisabled() {
            return this;
        }

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

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

    }

}
