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

import java.util.Collection;
import java.util.Set;
import java.util.concurrent.CompletableFuture;

/**
 * A distributed collection designed for holding unique elements.
 * <p>
 * All methods of {@code AsyncDistributedSet} immediately return a {@link CompletableFuture future}.
 * The returned future will be {@link CompletableFuture#complete completed} when the operation
 * completes.
 *
 * @param <E> set entry type
 */
public interface AsyncDistributedSet<E> extends DistributedPrimitive {

    @Override
    default DistributedPrimitive.Type type() {
        return DistributedPrimitive.Type.SET;
    }

    /**
     * Registers the specified listener to be notified whenever
     * the set is updated.
     *
     * @param listener listener to notify about set update events
     */
    CompletableFuture<Void> addListener(SetEventListener<E> listener);

    /**
     * Unregisters the specified listener.
     *
     * @param listener listener to unregister.
     * @return CompletableFuture that is completed when the operation completes
     */
    CompletableFuture<Void> removeListener(SetEventListener<E> listener);

    /**
     * Adds the specified element to this set if it is not already present (optional operation).
     * @param element element to add
     * @return {@code true} if this set did not already contain the specified element.
     */
    CompletableFuture<Boolean> add(E element);

    /**
     * Removes the specified element to this set if it is present (optional operation).
     * @param element element to remove
     * @return {@code true} if this set contained the specified element
     */
    CompletableFuture<Boolean> remove(E element);

    /**
     * Returns the number of elements in the set.
     * @return size of the set
     */
    CompletableFuture<Integer> size();

    /**
     * Returns if the set is empty.
     * @return {@code true} if this set is empty
     */
    CompletableFuture<Boolean> isEmpty();

    /**
     * Removes all elements from the set.
     */
    CompletableFuture<Void> clear();

    /**
     * Returns if this set contains the specified element.
     * @param element element to check
     * @return {@code true} if this set contains the specified element
     */
    CompletableFuture<Boolean> contains(E element);

    /**
     * Adds all of the elements in the specified collection to this set if they're not
     * already present (optional operation).
     * @param c collection containing elements to be added to this set
     * @return {@code true} if this set contains all elements in the collection
     */
    CompletableFuture<Boolean> addAll(Collection<? extends E> c);

    /**
     * Returns if this set contains all the elements in specified collection.
     * @param c collection
     * @return {@code true} if this set contains all elements in the collection
     */
    CompletableFuture<Boolean> containsAll(Collection<? extends E> c);

    /**
     * Retains only the elements in this set that are contained in the specified collection (optional operation).
     * @param c collection containing elements to be retained in this set
     * @return {@code true} if this set changed as a result of the call
     */
    CompletableFuture<Boolean> retainAll(Collection<? extends E> c);

    /**
     * Removes from this set all of its elements that are contained in the specified collection (optional operation).
     * If the specified collection is also a set, this operation effectively modifies this set so that its
     * value is the asymmetric set difference of the two sets.
     * @param c collection containing elements to be removed from this set
     * @return {@code true} if this set changed as a result of the call
     */
    CompletableFuture<Boolean> removeAll(Collection<? extends E> c);

    /**
     * Returns the entries as a immutable set. The returned set is a snapshot and will not reflect new changes made to
     * this AsyncDistributedSet
     * @return immutable set copy
     */
    CompletableFuture<? extends Set<E>> getAsImmutableSet();
}
