/*
 * 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 com.google.common.collect.ImmutableMultiset;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import org.onlab.util.Tools;
import org.onosproject.store.service.AsyncConsistentMultimap;
import org.onosproject.store.service.Versioned;

import java.util.Collection;
import java.util.EnumSet;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.function.BiConsumer;
import java.util.function.BinaryOperator;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.stream.Collector;
import java.util.stream.Collectors;

/**
 * An {@link AsyncConsistentMultimap} that maps its operation to operations to
 * a differently typed {@link AsyncConsistentMultimap} by transcoding operation
 * inputs and outputs while maintaining version numbers.
 *
 * @param <K2> key type of other map
 * @param <V2> value type of other map
 * @param <K1> key type of this map
 * @param <V1> value type of this map
 */
public class TranscodingAsyncConsistentMultimap<K1, V1, K2, V2>
        implements AsyncConsistentMultimap<K1, V1> {

    private final AsyncConsistentMultimap<K2, V2> backingMap;
    private final Function<K1, K2> keyEncoder;
    private final Function<K2, K1> keyDecoder;
    private final Function<V2, V1> valueDecoder;
    private final Function<V1, V2> valueEncoder;
    private final Function<? extends Versioned<V2>,
            ? extends Versioned<V1>> versionedValueTransform;
    private final Function<Versioned<Collection<? extends V2>>,
            Versioned<Collection<? extends V1>>> versionedValueCollectionDecode;
    private final Function<Collection<? extends V1>, Collection<V2>>
            valueCollectionEncode;

     public TranscodingAsyncConsistentMultimap(
            AsyncConsistentMultimap<K2, V2> backingMap,
            Function<K1, K2> keyEncoder,
            Function<K2, K1> keyDecoder,
            Function<V2, V1> valueDecoder,
            Function<V1, V2> valueEncoder) {
        this.backingMap = backingMap;
        this.keyEncoder = k -> k == null ? null : keyEncoder.apply(k);
        this.keyDecoder = k -> k == null ? null : keyDecoder.apply(k);
        this.valueDecoder = v -> v == null ? null : valueDecoder.apply(v);
        this.valueEncoder = v -> v == null ? null : valueEncoder.apply(v);
        this.versionedValueTransform = v -> v == null ? null :
                v.map(valueDecoder);
        this.versionedValueCollectionDecode = v -> v == null ? null :
                new Versioned<>(
                        v.value()
                                .stream()
                                .map(valueDecoder)
                                .collect(Collectors.toSet()),
                        v.version(),
                        v.creationTime());
         this.valueCollectionEncode = v -> v == null ? null :
                 v.stream().map(valueEncoder).collect(Collectors.toSet());
    }

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

    @Override
    public CompletableFuture<Boolean> isEmpty() {
        return backingMap.isEmpty();
    }

    @Override
    public CompletableFuture<Boolean> containsKey(K1 key) {
        try {
            return backingMap.containsKey(keyEncoder.apply(key));
        } catch (Exception e) {
            return Tools.exceptionalFuture(e);
        }
    }

    @Override
    public CompletableFuture<Boolean> containsValue(V1 value) {
        try {
            return backingMap.containsValue(valueEncoder.apply(value));
        } catch (Exception e) {
            return Tools.exceptionalFuture(e);
        }
    }

    @Override
    public CompletableFuture<Boolean> containsEntry(K1 key, V1 value) {
        try {
            return backingMap.containsEntry(keyEncoder.apply(key),
                                            valueEncoder.apply(value));
        } catch (Exception e) {
            return Tools.exceptionalFuture(e);
        }
    }

    @Override
    public CompletableFuture<Boolean> put(K1 key, V1 value) {
        try {
            return backingMap.put(keyEncoder.apply(key),
                                  valueEncoder.apply(value));
        } catch (Exception e) {
            return Tools.exceptionalFuture(e);
        }
    }

    @Override
    public CompletableFuture<Boolean> remove(K1 key, V1 value) {
        try {
            return backingMap.remove(keyEncoder.apply(key), valueEncoder
                    .apply(value));
        } catch (Exception e) {
            return Tools.exceptionalFuture(e);
        }
    }

    @Override
    public CompletableFuture<Boolean> removeAll(
            K1 key, Collection<? extends V1> values) {
        try {
            return backingMap.removeAll(
                    keyEncoder.apply(key),
                    values.stream().map(valueEncoder).collect(
                            Collectors.toSet()));
        } catch (Exception e) {
            return Tools.exceptionalFuture(e);
        }
    }

    @Override
    public CompletableFuture<Versioned<Collection<? extends V1>>>
    removeAll(K1 key) {
        try {
            return backingMap.removeAll(keyEncoder.apply(key))
                    .thenApply(versionedValueCollectionDecode);
        } catch (Exception e) {
            return Tools.exceptionalFuture(e);
        }
    }

    @Override
    public CompletableFuture<Boolean>
    putAll(K1 key, Collection<? extends V1> values) {
        try {
            return backingMap.putAll(keyEncoder.apply(key),
                                     valueCollectionEncode.apply(values));
        } catch (Exception e) {
            return Tools.exceptionalFuture(e);
        }
    }

    @Override
    public CompletableFuture<Versioned<Collection<? extends V1>>>
    replaceValues(K1 key, Collection<V1> values) {
        try {
            return backingMap.replaceValues(keyEncoder.apply(key),
                                     valueCollectionEncode.apply(values))
                    .thenApply(versionedValueCollectionDecode);
        } catch (Exception e) {
            return Tools.exceptionalFuture(e);
        }
    }

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

    @Override
    public CompletableFuture<Versioned<Collection<? extends V1>>> get(K1 key) {
        try {
            return backingMap.get(keyEncoder.apply(key))
                    .thenApply(versionedValueCollectionDecode);
        } catch (Exception e) {
            return Tools.exceptionalFuture(e);
        }
    }

    @Override
    public CompletableFuture<Set<K1>> keySet() {
        return backingMap.keySet().thenApply(s -> s.stream()
                .map(keyDecoder)
                .collect(Collectors.toSet()));
    }

    @Override
    public CompletableFuture<Multiset<K1>> keys() {
        return backingMap.keys().thenApply(s -> s.stream().map(keyDecoder)
                .collect(new MultisetCollector<>()));
    }

    @Override
    public CompletableFuture<Multiset<V1>> values() {
        return backingMap.values().thenApply(s ->
            s.stream().map(valueDecoder).collect(new MultisetCollector<>()));
    }

    @Override
    public CompletableFuture<Collection<Map.Entry<K1, V1>>> entries() {
        return backingMap.entries().thenApply(s -> s.stream()
        .map(e -> Maps.immutableEntry(keyDecoder.apply(e.getKey()),
                                      valueDecoder.apply(e.getValue())))
                .collect(Collectors.toSet()));
    }

    @Override
    public CompletableFuture<Map<K1, Collection<V1>>> asMap() {
        throw new UnsupportedOperationException("Unsupported operation.");
    }

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

    @Override
    public void addStatusChangeListener(Consumer<Status> listener) {
        backingMap.addStatusChangeListener(listener);
    }

    @Override
    public void removeStatusChangeListener(Consumer<Status> listener) {
        backingMap.removeStatusChangeListener(listener);
    }

    @Override
    public Collection<Consumer<Status>> statusChangeListeners() {
        return backingMap.statusChangeListeners();
    }

    private class MultisetCollector<T> implements Collector<T,
            ImmutableMultiset.Builder<T>,
            Multiset<T>> {

        @Override
        public Supplier<ImmutableMultiset.Builder<T>> supplier() {
            return ImmutableMultiset::builder;
        }

        @Override
        public BiConsumer<ImmutableMultiset.Builder<T>, T> accumulator() {
            return ((builder, t) -> builder.add(t));
        }

        @Override
        public BinaryOperator<ImmutableMultiset.Builder<T>> combiner() {
            return (a, b) -> {
                a.addAll(b.build());
                return a;
            };
        }

        @Override
        public Function<ImmutableMultiset.Builder<T>, Multiset<T>> finisher() {
            return ImmutableMultiset.Builder::build;
        }

        @Override
        public Set<Characteristics> characteristics() {
            return EnumSet.of(Characteristics.UNORDERED);
        }
    }
}
