// 
// Decompiled by Procyon v0.6.0
// 

package it.unimi.dsi.fastutil.ints;

import it.unimi.dsi.fastutil.SafeMath;
import java.util.Objects;
import java.util.function.Consumer;
import java.util.function.IntConsumer;
import java.util.NoSuchElementException;
import java.io.Serializable;

public final class IntBigListIterators
{
    public static final EmptyBigListIterator EMPTY_BIG_LIST_ITERATOR;
    
    private IntBigListIterators() {
    }
    
    public static IntBigListIterator singleton(final int element) {
        return new SingletonBigListIterator(element);
    }
    
    public static IntBigListIterator unmodifiable(final IntBigListIterator i) {
        return new UnmodifiableBigListIterator(i);
    }
    
    public static IntBigListIterator asBigListIterator(final IntListIterator i) {
        return new BigListIteratorListIterator(i);
    }
    
    static {
        EMPTY_BIG_LIST_ITERATOR = new EmptyBigListIterator();
    }
    
    public static class EmptyBigListIterator implements IntBigListIterator, Serializable, Cloneable
    {
        private static final long serialVersionUID = -7046029254386353129L;
        
        protected EmptyBigListIterator() {
        }
        
        @Override
        public boolean hasNext() {
            return false;
        }
        
        @Override
        public boolean hasPrevious() {
            return false;
        }
        
        @Override
        public int nextInt() {
            throw new NoSuchElementException();
        }
        
        @Override
        public int previousInt() {
            throw new NoSuchElementException();
        }
        
        @Override
        public long nextIndex() {
            return 0L;
        }
        
        @Override
        public long previousIndex() {
            return -1L;
        }
        
        @Override
        public long skip(final long n) {
            return 0L;
        }
        
        @Override
        public long back(final long n) {
            return 0L;
        }
        
        public Object clone() {
            return IntBigListIterators.EMPTY_BIG_LIST_ITERATOR;
        }
        
        @Override
        public void forEachRemaining(final IntConsumer action) {
        }
        
        @Deprecated
        @Override
        public void forEachRemaining(final Consumer<? super Integer> action) {
        }
        
        private Object readResolve() {
            return IntBigListIterators.EMPTY_BIG_LIST_ITERATOR;
        }
    }
    
    private static class SingletonBigListIterator implements IntBigListIterator
    {
        private final int element;
        private int curr;
        
        public SingletonBigListIterator(final int element) {
            this.element = element;
        }
        
        @Override
        public boolean hasNext() {
            return this.curr == 0;
        }
        
        @Override
        public boolean hasPrevious() {
            return this.curr == 1;
        }
        
        @Override
        public int nextInt() {
            if (!this.hasNext()) {
                throw new NoSuchElementException();
            }
            this.curr = 1;
            return this.element;
        }
        
        @Override
        public int previousInt() {
            if (!this.hasPrevious()) {
                throw new NoSuchElementException();
            }
            this.curr = 0;
            return this.element;
        }
        
        @Override
        public void forEachRemaining(final IntConsumer action) {
            Objects.requireNonNull(action);
            if (this.curr == 0) {
                action.accept(this.element);
                this.curr = 1;
            }
        }
        
        @Override
        public long nextIndex() {
            return this.curr;
        }
        
        @Override
        public long previousIndex() {
            return this.curr - 1;
        }
        
        @Override
        public long back(final long n) {
            if (n < 0L) {
                throw new IllegalArgumentException("Argument must be nonnegative: " + n);
            }
            if (n == 0L || this.curr < 1) {
                return 0L;
            }
            this.curr = 1;
            return 1L;
        }
        
        @Override
        public long skip(final long n) {
            if (n < 0L) {
                throw new IllegalArgumentException("Argument must be nonnegative: " + n);
            }
            if (n == 0L || this.curr > 0) {
                return 0L;
            }
            this.curr = 0;
            return 1L;
        }
    }
    
    public static class UnmodifiableBigListIterator implements IntBigListIterator
    {
        protected final IntBigListIterator i;
        
        public UnmodifiableBigListIterator(final IntBigListIterator i) {
            this.i = i;
        }
        
        @Override
        public boolean hasNext() {
            return this.i.hasNext();
        }
        
        @Override
        public boolean hasPrevious() {
            return this.i.hasPrevious();
        }
        
        @Override
        public int nextInt() {
            return this.i.nextInt();
        }
        
        @Override
        public int previousInt() {
            return this.i.previousInt();
        }
        
        @Override
        public long nextIndex() {
            return this.i.nextIndex();
        }
        
        @Override
        public long previousIndex() {
            return this.i.previousIndex();
        }
        
        @Override
        public void forEachRemaining(final IntConsumer action) {
            this.i.forEachRemaining(action);
        }
        
        @Deprecated
        @Override
        public void forEachRemaining(final Consumer<? super Integer> action) {
            this.i.forEachRemaining(action);
        }
    }
    
    public static class BigListIteratorListIterator implements IntBigListIterator
    {
        protected final IntListIterator i;
        
        protected BigListIteratorListIterator(final IntListIterator i) {
            this.i = i;
        }
        
        private int intDisplacement(final long n) {
            if (n < -2147483648L || n > 2147483647L) {
                throw new IndexOutOfBoundsException("This big iterator is restricted to 32-bit displacements");
            }
            return (int)n;
        }
        
        @Override
        public void set(final int ok) {
            this.i.set(ok);
        }
        
        @Override
        public void add(final int ok) {
            this.i.add(ok);
        }
        
        @Override
        public int back(final int n) {
            return this.i.back(n);
        }
        
        @Override
        public long back(final long n) {
            return this.i.back(this.intDisplacement(n));
        }
        
        @Override
        public void remove() {
            this.i.remove();
        }
        
        @Override
        public int skip(final int n) {
            return this.i.skip(n);
        }
        
        @Override
        public long skip(final long n) {
            return this.i.skip(this.intDisplacement(n));
        }
        
        @Override
        public boolean hasNext() {
            return this.i.hasNext();
        }
        
        @Override
        public boolean hasPrevious() {
            return this.i.hasPrevious();
        }
        
        @Override
        public int nextInt() {
            return this.i.nextInt();
        }
        
        @Override
        public int previousInt() {
            return this.i.previousInt();
        }
        
        @Override
        public long nextIndex() {
            return this.i.nextIndex();
        }
        
        @Override
        public long previousIndex() {
            return this.i.previousIndex();
        }
        
        @Override
        public void forEachRemaining(final IntConsumer action) {
            this.i.forEachRemaining(action);
        }
        
        @Deprecated
        @Override
        public void forEachRemaining(final Consumer<? super Integer> action) {
            this.i.forEachRemaining(action);
        }
    }
    
    public abstract static class AbstractIndexBasedBigIterator extends AbstractIntIterator
    {
        protected final long minPos;
        protected long pos;
        protected long lastReturned;
        
        protected AbstractIndexBasedBigIterator(final long minPos, final long initialPos) {
            this.minPos = minPos;
            this.pos = initialPos;
        }
        
        protected abstract int get(final long p0);
        
        protected abstract void remove(final long p0);
        
        protected abstract long getMaxPos();
        
        @Override
        public boolean hasNext() {
            return this.pos < this.getMaxPos();
        }
        
        @Override
        public int nextInt() {
            if (!this.hasNext()) {
                throw new NoSuchElementException();
            }
            final long lastReturned = this.pos++;
            this.lastReturned = lastReturned;
            return this.get(lastReturned);
        }
        
        @Override
        public void remove() {
            if (this.lastReturned == -1L) {
                throw new IllegalStateException();
            }
            this.remove(this.lastReturned);
            if (this.lastReturned < this.pos) {
                --this.pos;
            }
            this.lastReturned = -1L;
        }
        
        @Override
        public void forEachRemaining(final IntConsumer action) {
            while (this.pos < this.getMaxPos()) {
                final long lastReturned = this.pos++;
                this.lastReturned = lastReturned;
                action.accept(this.get(lastReturned));
            }
        }
        
        public long skip(long n) {
            if (n < 0L) {
                throw new IllegalArgumentException("Argument must be nonnegative: " + n);
            }
            final long max = this.getMaxPos();
            final long remaining = max - this.pos;
            if (n < remaining) {
                this.pos += n;
            }
            else {
                n = remaining;
                this.pos = max;
            }
            this.lastReturned = this.pos - 1L;
            return n;
        }
        
        @Override
        public int skip(final int n) {
            return SafeMath.safeLongToInt(this.skip((long)n));
        }
    }
    
    public abstract static class AbstractIndexBasedBigListIterator extends AbstractIndexBasedBigIterator implements IntBigListIterator
    {
        protected AbstractIndexBasedBigListIterator(final long minPos, final long initialPos) {
            super(minPos, initialPos);
        }
        
        protected abstract void add(final long p0, final int p1);
        
        protected abstract void set(final long p0, final int p1);
        
        @Override
        public boolean hasPrevious() {
            return this.pos > this.minPos;
        }
        
        @Override
        public int previousInt() {
            if (!this.hasPrevious()) {
                throw new NoSuchElementException();
            }
            final long n = this.pos - 1L;
            this.pos = n;
            this.lastReturned = n;
            return this.get(n);
        }
        
        @Override
        public long nextIndex() {
            return this.pos;
        }
        
        @Override
        public long previousIndex() {
            return this.pos - 1L;
        }
        
        @Override
        public void add(final int k) {
            this.add(this.pos++, k);
            this.lastReturned = -1L;
        }
        
        @Override
        public void set(final int k) {
            if (this.lastReturned == -1L) {
                throw new IllegalStateException();
            }
            this.set(this.lastReturned, k);
        }
        
        @Override
        public long back(long n) {
            if (n < 0L) {
                throw new IllegalArgumentException("Argument must be nonnegative: " + n);
            }
            final long remaining = this.pos - this.minPos;
            if (n < remaining) {
                this.pos -= n;
            }
            else {
                n = remaining;
                this.pos = this.minPos;
            }
            this.lastReturned = this.pos;
            return n;
        }
    }
}
