/*
 * Copyright 2018-present Open Networking Foundation
 *
 * 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.NavigableMap;
import java.util.NavigableSet;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Executor;
import java.util.function.BiFunction;
import java.util.function.Predicate;
import java.util.stream.Collectors;

import com.google.common.base.Throwables;
import com.google.common.collect.Maps;
import io.atomix.core.collection.impl.TranscodingAsyncDistributedCollection;
import io.atomix.core.map.impl.DelegatingAsyncDistributedNavigableMap;
import org.onosproject.store.primitives.MapUpdate;
import org.onosproject.store.primitives.TransactionId;
import org.onosproject.store.service.AsyncConsistentTreeMap;
import org.onosproject.store.service.AsyncIterator;
import org.onosproject.store.service.ConsistentMapException;
import org.onosproject.store.service.MapEvent;
import org.onosproject.store.service.MapEventListener;
import org.onosproject.store.service.TransactionLog;
import org.onosproject.store.service.Version;
import org.onosproject.store.service.Versioned;

/**
 * Atomix consistent tree map.
 */
public class AtomixConsistentTreeMap<V> implements AsyncConsistentTreeMap<V> {
    private final io.atomix.core.map.AsyncAtomicNavigableMap<String, V> atomixTreeMap;
    private final Map<MapEventListener<String, V>, io.atomix.core.map.AtomicMapEventListener<String, V>> listenerMap =
        Maps.newIdentityHashMap();

    public AtomixConsistentTreeMap(io.atomix.core.map.AsyncAtomicNavigableMap<String, V> atomixTreeMap) {
        this.atomixTreeMap = atomixTreeMap;
    }

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

    @Override
    public CompletableFuture<Integer> size() {
        return atomixTreeMap.size();
    }

    @Override
    public CompletableFuture<String> firstKey() {
        return atomixTreeMap.firstKey();
    }

    @Override
    public CompletableFuture<String> lastKey() {
        return atomixTreeMap.lastKey();
    }

    @Override
    public CompletableFuture<Map.Entry<String, Versioned<V>>> ceilingEntry(String key) {
        return atomixTreeMap.ceilingEntry(key).thenApply(this::toVersioned);
    }

    @Override
    public CompletableFuture<Map.Entry<String, Versioned<V>>> floorEntry(String key) {
        return atomixTreeMap.floorEntry(key).thenApply(this::toVersioned);
    }

    @Override
    public CompletableFuture<Map.Entry<String, Versioned<V>>> higherEntry(String key) {
        return atomixTreeMap.higherEntry(key).thenApply(this::toVersioned);
    }

    @Override
    public CompletableFuture<Map.Entry<String, Versioned<V>>> lowerEntry(String key) {
        return atomixTreeMap.lowerEntry(key).thenApply(this::toVersioned);
    }

    @Override
    public CompletableFuture<Map.Entry<String, Versioned<V>>> firstEntry() {
        return atomixTreeMap.firstEntry().thenApply(this::toVersioned);
    }

    @Override
    public CompletableFuture<Map.Entry<String, Versioned<V>>> lastEntry() {
        return atomixTreeMap.lastEntry().thenApply(this::toVersioned);
    }

    @Override
    public CompletableFuture<Map.Entry<String, Versioned<V>>> pollFirstEntry() {
        throw new UnsupportedOperationException();
    }

    @Override
    public CompletableFuture<Map.Entry<String, Versioned<V>>> pollLastEntry() {
        throw new UnsupportedOperationException();
    }

    @Override
    public CompletableFuture<Boolean> containsKey(String key) {
        return atomixTreeMap.containsKey(key);
    }

    @Override
    public CompletableFuture<String> lowerKey(String key) {
        return atomixTreeMap.lowerKey(key);
    }

    @Override
    public CompletableFuture<String> floorKey(String key) {
        return atomixTreeMap.floorKey(key);
    }

    @Override
    public CompletableFuture<String> ceilingKey(String key) {
        return atomixTreeMap.ceilingKey(key);
    }

    @Override
    public CompletableFuture<Versioned<V>> get(String key) {
        return atomixTreeMap.get(key).thenApply(this::toVersioned);
    }

    @Override
    public CompletableFuture<String> higherKey(String key) {
        return atomixTreeMap.higherKey(key);
    }

    @Override
    public CompletableFuture<NavigableSet<String>> navigableKeySet() {
        return CompletableFuture.completedFuture(atomixTreeMap.navigableKeySet().sync());
    }

    @Override
    public CompletableFuture<Versioned<V>> getOrDefault(String key, V defaultValue) {
        return atomixTreeMap.getOrDefault(key, defaultValue).thenApply(this::toVersioned);
    }

    @Override
    public CompletableFuture<NavigableMap<String, V>> subMap(
        String upperKey, String lowerKey, boolean inclusiveUpper, boolean inclusiveLower) {
        return CompletableFuture.completedFuture(
            new DelegatingAsyncDistributedNavigableMap<>(
                atomixTreeMap.subMap(lowerKey, inclusiveLower, upperKey, inclusiveUpper)).sync());
    }

    @Override
    public CompletableFuture<Versioned<V>> computeIf(
        String key,
        Predicate<? super V> condition, BiFunction<? super String, ? super V, ? extends V> remappingFunction) {
        return adapt(atomixTreeMap.computeIf(key, condition, remappingFunction)).thenApply(this::toVersioned);
    }

    @Override
    public CompletableFuture<Versioned<V>> put(String key, V value) {
        return adapt(atomixTreeMap.put(key, value)).thenApply(this::toVersioned);
    }

    @Override
    public CompletableFuture<Versioned<V>> putAndGet(String key, V value) {
        return adapt(atomixTreeMap.putAndGet(key, value)).thenApply(this::toVersioned);
    }

    @Override
    public CompletableFuture<Versioned<V>> remove(String key) {
        return adapt(atomixTreeMap.remove(key)).thenApply(this::toVersioned);
    }

    @Override
    public CompletableFuture<Set<String>> keySet() {
        return CompletableFuture.completedFuture(atomixTreeMap.keySet().sync());
    }

    @Override
    public CompletableFuture<Set<Map.Entry<String, Versioned<V>>>> entrySet() {
        return CompletableFuture.completedFuture(atomixTreeMap.entrySet().stream()
            .map(this::toVersioned)
            .collect(Collectors.toSet()));
    }

    @Override
    public CompletableFuture<Versioned<V>> putIfAbsent(String key, V value) {
        return adapt(atomixTreeMap.putIfAbsent(key, value)).thenApply(this::toVersioned);
    }

    @Override
    public CompletableFuture<Boolean> remove(String key, V value) {
        return adapt(atomixTreeMap.remove(key, value));
    }

    @Override
    public CompletableFuture<Boolean> remove(String key, long version) {
        return adapt(atomixTreeMap.remove(key, version));
    }

    @Override
    public CompletableFuture<Versioned<V>> replace(String key, V value) {
        return adapt(atomixTreeMap.replace(key, value)).thenApply(this::toVersioned);
    }

    @Override
    public CompletableFuture<Boolean> replace(String key, V oldValue, V newValue) {
        return adapt(atomixTreeMap.replace(key, oldValue, newValue));
    }

    @Override
    public CompletableFuture<Boolean> replace(String key, long oldVersion, V newValue) {
        return adapt(atomixTreeMap.replace(key, oldVersion, newValue));
    }

    @Override
    public CompletableFuture<Boolean> containsValue(V value) {
        return atomixTreeMap.containsValue(value);
    }

    @Override
    public CompletableFuture<AsyncIterator<Map.Entry<String, Versioned<V>>>> iterator() {
        io.atomix.core.iterator.AsyncIterator<Map.Entry<String, io.atomix.utils.time.Versioned<V>>> atomixIterator
            = atomixTreeMap.entrySet().iterator();
        return CompletableFuture.completedFuture(new AsyncIterator<Map.Entry<String, Versioned<V>>>() {
            @Override
            public CompletableFuture<Boolean> hasNext() {
                return atomixIterator.hasNext();
            }

            @Override
            public CompletableFuture<Map.Entry<String, Versioned<V>>> next() {
                return atomixIterator.next()
                    .thenApply(entry -> Maps.immutableEntry(entry.getKey(), toVersioned(entry.getValue())));
            }
        });
    }

    @Override
    public CompletableFuture<Void> clear() {
        return atomixTreeMap.clear();
    }

    @Override
    public CompletableFuture<Collection<Versioned<V>>> values() {
        return CompletableFuture.completedFuture(
            new TranscodingAsyncDistributedCollection<Versioned<V>, io.atomix.utils.time.Versioned<V>>(
                atomixTreeMap.values(),
                e -> new io.atomix.utils.time.Versioned<>(e.value(), e.version()),
                e -> new Versioned<>(e.value(), e.version())).sync());
    }

    @Override
    public synchronized CompletableFuture<Void> addListener(MapEventListener<String, V> listener, Executor executor) {
        io.atomix.core.map.AtomicMapEventListener<String, V> atomixListener = event ->
            listener.event(new MapEvent<String, V>(
                MapEvent.Type.valueOf(event.type().name()),
                name(),
                event.key(),
                toVersioned(event.newValue()),
                toVersioned(event.oldValue())));
        listenerMap.put(listener, atomixListener);
        return atomixTreeMap.addListener(atomixListener, executor);
    }

    @Override
    public CompletableFuture<Void> removeListener(MapEventListener<String, V> listener) {
        io.atomix.core.map.AtomicMapEventListener<String, V> atomixListener = listenerMap.remove(listener);
        if (atomixListener != null) {
            return atomixTreeMap.removeListener(atomixListener);
        }
        return CompletableFuture.completedFuture(null);
    }

    @Override
    public CompletableFuture<Version> begin(TransactionId transactionId) {
        throw new UnsupportedOperationException();
    }

    @Override
    public CompletableFuture<Boolean> prepare(TransactionLog<MapUpdate<String, V>> transactionLog) {
        throw new UnsupportedOperationException();
    }

    @Override
    public CompletableFuture<Boolean> prepareAndCommit(TransactionLog<MapUpdate<String, V>> transactionLog) {
        throw new UnsupportedOperationException();
    }

    @Override
    public CompletableFuture<Void> commit(TransactionId transactionId) {
        throw new UnsupportedOperationException();
    }

    @Override
    public CompletableFuture<Void> rollback(TransactionId transactionId) {
        throw new UnsupportedOperationException();
    }

    private <T> CompletableFuture<T> adapt(CompletableFuture<T> future) {
        CompletableFuture<T> newFuture = new CompletableFuture<>();
        future.whenComplete((result, error) -> {
            if (error == null) {
                newFuture.complete(result);
            } else {
                Throwable cause = Throwables.getRootCause(error);
                if (cause instanceof io.atomix.primitive.PrimitiveException.ConcurrentModification) {
                    newFuture.completeExceptionally(
                        new ConsistentMapException.ConcurrentModification(error.getMessage()));
                } else if (cause instanceof io.atomix.primitive.PrimitiveException.Timeout) {
                    newFuture.completeExceptionally(new ConsistentMapException.Timeout(error.getMessage()));
                } else if (cause instanceof io.atomix.primitive.PrimitiveException.Interrupted) {
                    newFuture.completeExceptionally(new ConsistentMapException.Interrupted());
                } else if (cause instanceof io.atomix.primitive.PrimitiveException.Unavailable) {
                    newFuture.completeExceptionally(new ConsistentMapException.Unavailable());
                } else if (cause instanceof io.atomix.primitive.PrimitiveException) {
                    newFuture.completeExceptionally(new ConsistentMapException(cause.getMessage()));
                }
            }
        });
        return newFuture;
    }

    private Versioned<V> toVersioned(io.atomix.utils.time.Versioned<V> versioned) {
        return versioned != null
            ? new Versioned<>(versioned.value(), versioned.version(), versioned.creationTime())
            : null;
    }

    private Map.Entry<String, Versioned<V>> toVersioned(Map.Entry<String, io.atomix.utils.time.Versioned<V>> entry) {
        return entry != null ? Maps.immutableEntry(entry.getKey(), toVersioned(entry.getValue())) : null;
    }
}
