/*
 * Copyright 2015-present 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.onlab.util;

import java.util.Collection;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.Predicate;

import com.google.common.collect.Iterators;
import static com.google.common.base.Preconditions.checkNotNull;

/**
 * A Set providing additional get, insertOrReplace and conditionalRemove methods.
 */
public class ExtendedSet<E> implements Set<E> {

    private final Map<E, E> map;

    /**
     * Constructs a new instance by backing it with the supplied Map.
     * <p>
     * Constructed ExtendedSet will have the same concurrency properties as that of the supplied Map.
     *
     * @param map input map.
     */
    public ExtendedSet(Map<E, E> map) {
        this.map = map;
    }

    /**
     * Returns set element that is equal to the specified object.
     * @param o object
     * @return set element that is equal to the input argument or null if no such set element exists
     */
    public E get(Object o) {
        return map.get(o);
    }

    /**
     * Inserts the entry if it is not already in the set otherwise replaces the existing entry
     * if the supplied predicate evaluates to true.
     * @param entry entry to add
     * @param entryTest predicate that is used to evaluate if the existing entry should be replaced
     * @return true if the set is updated; false otherwise
     */
    public boolean insertOrReplace(E entry, Predicate<E> entryTest) {
        AtomicBoolean updated = new AtomicBoolean(false);
        map.compute(checkNotNull(entry), (k, v) -> {
            if (v == null || entryTest.test(v)) {
                updated.set(true);
                return entry;
            }
            return v;
        });
        return updated.get();
    }

    /**
     * Removes the entry if the supplied predicate evaluates to true.
     * @param entry entry to remove
     * @param entryTest predicate that is used to evaluated aginst the existing entry. Return value of
     * true implies value should be removed.
     * @return true if the set is updated; false otherwise
     */
    public boolean conditionalRemove(E entry, Predicate<E> entryTest) {
        AtomicBoolean updated = new AtomicBoolean(false);
        map.compute(entry, (k, v) -> {
            if (entryTest.test(v)) {
                updated.set(true);
                return null;
            }
            return v;
        });
        return updated.get();
    }

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

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

    @Override
    public boolean contains(Object o) {
        return map.containsKey(o);
    }

    @Override
    public Iterator<E> iterator() {
        return Iterators.transform(map.entrySet().iterator(), Map.Entry::getValue);
    }

    @Override
    public Object[] toArray() {
        return map.values().toArray();
    }

    @Override
    public <T> T[] toArray(T[] a) {
        return map.values().toArray(a);
    }

    @Override
    public boolean add(E e) {
        return map.putIfAbsent(e, e) == null;
    }

    @Override
    public boolean remove(Object o) {
        return map.remove(o) != null;
    }

    @Override
    public boolean containsAll(Collection<?> c) {
        return c.stream()
                .map(map::containsKey)
                .reduce(Boolean::logicalAnd)
                .orElse(true);
    }

    @Override
    public boolean addAll(Collection<? extends E> c) {
        return c.stream()
                .map(e -> map.putIfAbsent(e, e) == null)
                .reduce(Boolean::logicalOr)
                .orElse(false);
    }

    @Override
    public boolean retainAll(Collection<?> c) {
        return c.stream()
                .filter(e -> !map.containsKey(e))
                .map(e -> map.remove(e) != null)
                .reduce(Boolean::logicalOr)
                .orElse(false);
    }

    @Override
    public boolean removeAll(Collection<?> c) {
        return c.stream()
                .map(e -> map.remove(e) != null)
                .reduce(Boolean::logicalOr)
                .orElse(false);
    }

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