/*
 * Copyright 2016-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.onosproject.store.primitives;

import java.lang.reflect.Array;
import java.util.Collection;
import java.util.Iterator;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

import org.onosproject.store.service.AsyncDistributedSet;
import org.onosproject.store.service.DistributedSet;
import org.onosproject.store.service.SetEventListener;
import org.onosproject.store.service.StorageException;
import org.onosproject.store.service.Synchronous;

/**
 * Implementation of {@link DistributedSet} that merely delegates to a {@link AsyncDistributedSet}
 * and waits for the operation to complete.

 * @param <E> set element type
 */
public class DefaultDistributedSet<E> extends Synchronous<AsyncDistributedSet<E>> implements DistributedSet<E> {

    private final long operationTimeoutMillis;

    private final AsyncDistributedSet<E> asyncSet;

    public DefaultDistributedSet(AsyncDistributedSet<E> asyncSet, long operationTimeoutMillis) {
        super(asyncSet);
        this.asyncSet = asyncSet;
        this.operationTimeoutMillis = operationTimeoutMillis;
    }

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

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

    @SuppressWarnings("unchecked")
    @Override
    public boolean contains(Object o) {
        return complete(asyncSet.contains((E) o));
    }

    @Override
    public Iterator<E> iterator() {
        return complete(asyncSet.getAsImmutableSet()).iterator();
    }

    @Override
    public Object[] toArray() {
        return complete(asyncSet.getAsImmutableSet()).stream().toArray();
    }

    @SuppressWarnings("unchecked")
    @Override
    public <T> T[] toArray(T[] a) {
        // TODO: Optimize this to only allocate a new array if the set size
        // is larger than the array.length. If the set size is smaller than
        // the array.length then copy the data into the array and set the
        // last element in the array to be null.
        final T[] resizedArray =
                (T[]) Array.newInstance(a.getClass().getComponentType(), complete(asyncSet.getAsImmutableSet()).size());
        return complete(asyncSet.getAsImmutableSet()).toArray(resizedArray);
    }

    @Override
    public boolean add(E e) {
        return complete(asyncSet.add(e));
    }

    @SuppressWarnings("unchecked")
    @Override
    public boolean remove(Object o) {
        return complete(asyncSet.remove((E) o));
    }

    @SuppressWarnings("unchecked")
    @Override
    public boolean containsAll(Collection<?> c) {
        return complete(asyncSet.containsAll((Collection<? extends E>) c));
    }

    @Override
    public boolean addAll(Collection<? extends E> c) {
        return complete(asyncSet.addAll(c));
    }

    @SuppressWarnings("unchecked")
    @Override
    public boolean retainAll(Collection<?> c) {
        return complete(asyncSet.retainAll((Collection<? extends E>) c));
    }

    @SuppressWarnings("unchecked")
    @Override
    public boolean removeAll(Collection<?> c) {
        return complete(asyncSet.removeAll((Collection<? extends E>) c));
    }

    @Override
    public void clear() {
        complete(asyncSet.clear());
    }

    @Override
    public void addListener(SetEventListener<E> listener) {
        complete(asyncSet.addListener(listener));
    }

    @Override
    public void removeListener(SetEventListener<E> listener) {
        complete(asyncSet.removeListener(listener));
    }

    private <T> T complete(CompletableFuture<T> future) {
        try {
            return future.get(operationTimeoutMillis, TimeUnit.MILLISECONDS);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            throw new StorageException.Interrupted();
        } catch (TimeoutException e) {
            throw new StorageException.Timeout();
        } catch (ExecutionException e) {
            if (e.getCause() instanceof StorageException) {
                throw (StorageException) e.getCause();
            } else {
                throw new StorageException(e.getCause());
            }
        }
    }
}
