package org.xbib.datastructures.immutable;

import java.util.Collection;
import java.util.EnumSet;
import java.util.Spliterator;
import java.util.function.Consumer;
import static org.xbib.datastructures.immutable.ImmutableEnumMap.getOnlyElement;
import static org.xbib.datastructures.immutable.UnmodifiableIterator.unmodifiableIterator;

/**
 * Implementation of {@link ImmutableSet} backed by a non-empty {@link EnumSet}.
 */
final class ImmutableEnumSet<E extends Enum<E>> extends ImmutableSet<E> {
    static ImmutableSet<?> asImmutable(EnumSet<?> set) {
        return switch (set.size()) {
            case 0 -> ImmutableSet.of();
            case 1 -> ImmutableSet.of(getOnlyElement(set.iterator()));
            default -> new ImmutableEnumSet<>(set);
        };
    }

    private final transient EnumSet<E> delegate;

    private ImmutableEnumSet(EnumSet<E> delegate) {
        this.delegate = delegate;
    }

    @Override
    boolean isPartialView() {
        return false;
    }

    @Override
    public UnmodifiableIterator<E> iterator() {
        return unmodifiableIterator(delegate.iterator());
    }

    @Override
    public Spliterator<E> spliterator() {
        return delegate.spliterator();
    }

    @Override
    public void forEach(Consumer<? super E> action) {
        delegate.forEach(action);
    }

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

    @Override
    public boolean contains(Object object) {
        return delegate.contains(object);
    }

    @Override
    public boolean containsAll(Collection<?> collection) {
        if (collection instanceof ImmutableEnumSet<?>) {
            collection = ((ImmutableEnumSet<?>) collection).delegate;
        }
        return delegate.containsAll(collection);
    }

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

    @Override
    public boolean equals(Object object) {
        if (object == this) {
            return true;
        }
        if (object instanceof ImmutableEnumSet) {
            object = ((ImmutableEnumSet<?>) object).delegate;
        }
        return delegate.equals(object);
    }

    @Override
    boolean isHashCodeFast() {
        return true;
    }

    private transient int hashCode;

    @Override
    public int hashCode() {
        int result = hashCode;
        return (result == 0) ? hashCode = delegate.hashCode() : result;
    }

    @Override
    public String toString() {
        return delegate.toString();
    }
}
