/*
 * Decompiled with CFR 0.152.
 */
package org.jivesoftware.smack.util;

import java.util.AbstractQueue;
import java.util.Collection;
import java.util.Iterator;
import java.util.NoSuchElementException;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

public class ArrayBlockingQueueWithShutdown<E>
extends AbstractQueue<E>
implements BlockingQueue<E> {
    private final E[] items;
    private int takeIndex;
    private int putIndex;
    private int count;
    private final ReentrantLock lock;
    private final Condition notEmpty;
    private final Condition notFull;
    private volatile boolean isShutdown = false;

    private final int inc(int i) {
        return ++i == this.items.length ? 0 : i;
    }

    private final void insert(E e) {
        this.items[this.putIndex] = e;
        this.putIndex = this.inc(this.putIndex);
        ++this.count;
        this.notEmpty.signal();
    }

    private final E extract() {
        E e = this.items[this.takeIndex];
        this.items[this.takeIndex] = null;
        this.takeIndex = this.inc(this.takeIndex);
        --this.count;
        this.notFull.signal();
        return e;
    }

    private final void removeAt(int i) {
        if (i == this.takeIndex) {
            this.items[this.takeIndex] = null;
            this.takeIndex = this.inc(this.takeIndex);
        } else {
            int nexti;
            while ((nexti = this.inc(i)) != this.putIndex) {
                this.items[i] = this.items[nexti];
                i = nexti;
            }
            this.items[i] = null;
            this.putIndex = i;
        }
        --this.count;
        this.notFull.signal();
    }

    private static final void checkNotNull(Object o) {
        if (o == null) {
            throw new NullPointerException();
        }
    }

    private final void checkNotShutdown() throws InterruptedException {
        if (this.isShutdown) {
            throw new InterruptedException();
        }
    }

    private final boolean hasNoElements() {
        return this.count == 0;
    }

    private final boolean hasElements() {
        return !this.hasNoElements();
    }

    private final boolean isFull() {
        return this.count == this.items.length;
    }

    private final boolean isNotFull() {
        return !this.isFull();
    }

    public ArrayBlockingQueueWithShutdown(int capacity) {
        this(capacity, false);
    }

    public ArrayBlockingQueueWithShutdown(int capacity, boolean fair) {
        if (capacity <= 0) {
            throw new IllegalArgumentException();
        }
        this.items = new Object[capacity];
        this.lock = new ReentrantLock(fair);
        this.notEmpty = this.lock.newCondition();
        this.notFull = this.lock.newCondition();
    }

    /*
     * WARNING - Removed try catching itself - possible behaviour change.
     */
    public void shutdown() {
        this.lock.lock();
        try {
            this.isShutdown = true;
            this.notEmpty.signalAll();
            this.notFull.signalAll();
        }
        finally {
            this.lock.unlock();
        }
    }

    /*
     * WARNING - Removed try catching itself - possible behaviour change.
     */
    public void start() {
        this.lock.lock();
        try {
            this.isShutdown = false;
        }
        finally {
            this.lock.unlock();
        }
    }

    /*
     * WARNING - Removed try catching itself - possible behaviour change.
     */
    public boolean isShutdown() {
        this.lock.lock();
        try {
            boolean bl = this.isShutdown;
            return bl;
        }
        finally {
            this.lock.unlock();
        }
    }

    /*
     * WARNING - Removed try catching itself - possible behaviour change.
     */
    @Override
    public E poll() {
        this.lock.lock();
        try {
            E e;
            if (this.hasNoElements()) {
                E e2 = null;
                return e2;
            }
            E e3 = e = this.extract();
            return e3;
        }
        finally {
            this.lock.unlock();
        }
    }

    /*
     * WARNING - Removed try catching itself - possible behaviour change.
     */
    @Override
    public E peek() {
        this.lock.lock();
        try {
            E e = this.hasNoElements() ? null : (E)this.items[this.takeIndex];
            return e;
        }
        finally {
            this.lock.unlock();
        }
    }

    /*
     * WARNING - Removed try catching itself - possible behaviour change.
     */
    @Override
    public boolean offer(E e) {
        ArrayBlockingQueueWithShutdown.checkNotNull(e);
        this.lock.lock();
        try {
            if (this.isFull() || this.isShutdown) {
                boolean bl = false;
                return bl;
            }
            this.insert(e);
            boolean bl = true;
            return bl;
        }
        finally {
            this.lock.unlock();
        }
    }

    /*
     * WARNING - Removed try catching itself - possible behaviour change.
     */
    @Override
    public void put(E e) throws InterruptedException {
        ArrayBlockingQueueWithShutdown.checkNotNull(e);
        this.lock.lockInterruptibly();
        try {
            while (this.isFull()) {
                try {
                    this.notFull.await();
                    this.checkNotShutdown();
                }
                catch (InterruptedException ie) {
                    this.notFull.signal();
                    throw ie;
                }
            }
            this.insert(e);
        }
        finally {
            this.lock.unlock();
        }
    }

    /*
     * Exception decompiling
     */
    @Override
    public boolean offer(E e, long timeout, TimeUnit unit) throws InterruptedException {
        /*
         * This method has failed to decompile.  When submitting a bug report, please provide this stack trace, and (if you hold appropriate legal rights) the relevant class file.
         * 
         * org.benf.cfr.reader.util.ConfusedCFRException: Tried to end blocks [0[TRYBLOCK]], but top level block is 7[UNCONDITIONALDOLOOP]
         *     at org.benf.cfr.reader.bytecode.analysis.opgraph.Op04StructuredStatement.processEndingBlocks(Op04StructuredStatement.java:435)
         *     at org.benf.cfr.reader.bytecode.analysis.opgraph.Op04StructuredStatement.buildNestedBlocks(Op04StructuredStatement.java:484)
         *     at org.benf.cfr.reader.bytecode.analysis.opgraph.Op03SimpleStatement.createInitialStructuredBlock(Op03SimpleStatement.java:736)
         *     at org.benf.cfr.reader.bytecode.CodeAnalyser.getAnalysisInner(CodeAnalyser.java:850)
         *     at org.benf.cfr.reader.bytecode.CodeAnalyser.getAnalysisOrWrapFail(CodeAnalyser.java:278)
         *     at org.benf.cfr.reader.bytecode.CodeAnalyser.getAnalysis(CodeAnalyser.java:201)
         *     at org.benf.cfr.reader.entities.attributes.AttributeCode.analyse(AttributeCode.java:94)
         *     at org.benf.cfr.reader.entities.Method.analyse(Method.java:531)
         *     at org.benf.cfr.reader.entities.ClassFile.analyseMid(ClassFile.java:1055)
         *     at org.benf.cfr.reader.entities.ClassFile.analyseTop(ClassFile.java:942)
         *     at org.benf.cfr.reader.Driver.doClass(Driver.java:84)
         *     at org.benf.cfr.reader.CfrDriverImpl.analyse(CfrDriverImpl.java:78)
         *     at org.benf.cfr.reader.Main.main(Main.java:54)
         */
        throw new IllegalStateException("Decompilation failed");
    }

    /*
     * WARNING - Removed try catching itself - possible behaviour change.
     */
    @Override
    public E take() throws InterruptedException {
        this.lock.lockInterruptibly();
        try {
            E e;
            this.checkNotShutdown();
            try {
                while (this.hasNoElements()) {
                    this.notEmpty.await();
                    this.checkNotShutdown();
                }
            }
            catch (InterruptedException ie) {
                this.notEmpty.signal();
                throw ie;
            }
            E e2 = e = this.extract();
            return e2;
        }
        finally {
            this.lock.unlock();
        }
    }

    /*
     * Exception decompiling
     */
    @Override
    public E poll(long timeout, TimeUnit unit) throws InterruptedException {
        /*
         * This method has failed to decompile.  When submitting a bug report, please provide this stack trace, and (if you hold appropriate legal rights) the relevant class file.
         * 
         * org.benf.cfr.reader.util.ConfusedCFRException: Tried to end blocks [0[TRYBLOCK]], but top level block is 7[UNCONDITIONALDOLOOP]
         *     at org.benf.cfr.reader.bytecode.analysis.opgraph.Op04StructuredStatement.processEndingBlocks(Op04StructuredStatement.java:435)
         *     at org.benf.cfr.reader.bytecode.analysis.opgraph.Op04StructuredStatement.buildNestedBlocks(Op04StructuredStatement.java:484)
         *     at org.benf.cfr.reader.bytecode.analysis.opgraph.Op03SimpleStatement.createInitialStructuredBlock(Op03SimpleStatement.java:736)
         *     at org.benf.cfr.reader.bytecode.CodeAnalyser.getAnalysisInner(CodeAnalyser.java:850)
         *     at org.benf.cfr.reader.bytecode.CodeAnalyser.getAnalysisOrWrapFail(CodeAnalyser.java:278)
         *     at org.benf.cfr.reader.bytecode.CodeAnalyser.getAnalysis(CodeAnalyser.java:201)
         *     at org.benf.cfr.reader.entities.attributes.AttributeCode.analyse(AttributeCode.java:94)
         *     at org.benf.cfr.reader.entities.Method.analyse(Method.java:531)
         *     at org.benf.cfr.reader.entities.ClassFile.analyseMid(ClassFile.java:1055)
         *     at org.benf.cfr.reader.entities.ClassFile.analyseTop(ClassFile.java:942)
         *     at org.benf.cfr.reader.Driver.doClass(Driver.java:84)
         *     at org.benf.cfr.reader.CfrDriverImpl.analyse(CfrDriverImpl.java:78)
         *     at org.benf.cfr.reader.Main.main(Main.java:54)
         */
        throw new IllegalStateException("Decompilation failed");
    }

    /*
     * WARNING - Removed try catching itself - possible behaviour change.
     */
    @Override
    public int remainingCapacity() {
        this.lock.lock();
        try {
            int n = this.items.length - this.count;
            return n;
        }
        finally {
            this.lock.unlock();
        }
    }

    /*
     * WARNING - Removed try catching itself - possible behaviour change.
     */
    @Override
    public int drainTo(Collection<? super E> c) {
        ArrayBlockingQueueWithShutdown.checkNotNull(c);
        if (c == this) {
            throw new IllegalArgumentException();
        }
        this.lock.lock();
        try {
            int n;
            int i = this.takeIndex;
            for (n = 0; n < this.count; ++n) {
                c.add(this.items[i]);
                this.items[i] = null;
                i = this.inc(i);
            }
            if (n > 0) {
                this.count = 0;
                this.putIndex = 0;
                this.takeIndex = 0;
                this.notFull.signalAll();
            }
            int n2 = n;
            return n2;
        }
        finally {
            this.lock.unlock();
        }
    }

    /*
     * WARNING - Removed try catching itself - possible behaviour change.
     */
    @Override
    public int drainTo(Collection<? super E> c, int maxElements) {
        ArrayBlockingQueueWithShutdown.checkNotNull(c);
        if (c == this) {
            throw new IllegalArgumentException();
        }
        if (maxElements <= 0) {
            return 0;
        }
        this.lock.lock();
        try {
            int n;
            int max;
            int i = this.takeIndex;
            int n2 = max = maxElements < this.count ? maxElements : this.count;
            for (n = 0; n < max; ++n) {
                c.add(this.items[i]);
                this.items[i] = null;
                i = this.inc(i);
            }
            if (n > 0) {
                this.count -= n;
                this.takeIndex = i;
                this.notFull.signalAll();
            }
            int n3 = n;
            return n3;
        }
        finally {
            this.lock.unlock();
        }
    }

    /*
     * WARNING - Removed try catching itself - possible behaviour change.
     */
    @Override
    public int size() {
        this.lock.lock();
        try {
            int n = this.count;
            return n;
        }
        finally {
            this.lock.unlock();
        }
    }

    /*
     * WARNING - Removed try catching itself - possible behaviour change.
     */
    @Override
    public Iterator<E> iterator() {
        this.lock.lock();
        try {
            Itr itr = new Itr();
            return itr;
        }
        finally {
            this.lock.unlock();
        }
    }

    private class Itr
    implements Iterator<E> {
        private int nextIndex;
        private E nextItem;
        private int lastRet = -1;

        Itr() {
            if (ArrayBlockingQueueWithShutdown.this.count == 0) {
                this.nextIndex = -1;
            } else {
                this.nextIndex = ArrayBlockingQueueWithShutdown.this.takeIndex;
                this.nextItem = ArrayBlockingQueueWithShutdown.this.items[ArrayBlockingQueueWithShutdown.this.takeIndex];
            }
        }

        @Override
        public boolean hasNext() {
            return this.nextIndex >= 0;
        }

        private void checkNext() {
            if (this.nextIndex == ArrayBlockingQueueWithShutdown.this.putIndex) {
                this.nextIndex = -1;
                this.nextItem = null;
            } else {
                this.nextItem = ArrayBlockingQueueWithShutdown.this.items[this.nextIndex];
                if (this.nextItem == null) {
                    this.nextIndex = -1;
                }
            }
        }

        /*
         * WARNING - Removed try catching itself - possible behaviour change.
         */
        @Override
        public E next() {
            ArrayBlockingQueueWithShutdown.this.lock.lock();
            try {
                if (this.nextIndex < 0) {
                    throw new NoSuchElementException();
                }
                this.lastRet = this.nextIndex;
                Object e = this.nextItem;
                this.nextIndex = ArrayBlockingQueueWithShutdown.this.inc(this.nextIndex);
                this.checkNext();
                Object e2 = e;
                return e2;
            }
            finally {
                ArrayBlockingQueueWithShutdown.this.lock.unlock();
            }
        }

        /*
         * WARNING - Removed try catching itself - possible behaviour change.
         */
        @Override
        public void remove() {
            ArrayBlockingQueueWithShutdown.this.lock.lock();
            try {
                int i = this.lastRet;
                if (i < 0) {
                    throw new IllegalStateException();
                }
                this.lastRet = -1;
                int ti = ArrayBlockingQueueWithShutdown.this.takeIndex;
                ArrayBlockingQueueWithShutdown.this.removeAt(i);
                this.nextIndex = i == ti ? ArrayBlockingQueueWithShutdown.this.takeIndex : i;
                this.checkNext();
            }
            finally {
                ArrayBlockingQueueWithShutdown.this.lock.unlock();
            }
        }
    }
}
