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

package com.google.crypto.tink.streamingaead;

import java.util.Iterator;
import java.security.GeneralSecurityException;
import java.io.IOException;
import java.io.BufferedInputStream;
import com.google.crypto.tink.StreamingAead;
import java.util.List;
import javax.annotation.concurrent.GuardedBy;
import java.io.InputStream;

final class InputStreamDecrypter extends InputStream
{
    @GuardedBy("this")
    boolean attemptedMatching;
    @GuardedBy("this")
    InputStream matchingStream;
    @GuardedBy("this")
    InputStream ciphertextStream;
    List<StreamingAead> primitives;
    byte[] associatedData;
    
    public InputStreamDecrypter(final List<StreamingAead> primitives, final InputStream ciphertextStream, final byte[] associatedData) {
        this.attemptedMatching = false;
        this.matchingStream = null;
        this.primitives = primitives;
        if (ciphertextStream.markSupported()) {
            this.ciphertextStream = ciphertextStream;
        }
        else {
            this.ciphertextStream = new BufferedInputStream(ciphertextStream);
        }
        this.ciphertextStream.mark(Integer.MAX_VALUE);
        this.associatedData = associatedData.clone();
    }
    
    @GuardedBy("this")
    private void rewind() throws IOException {
        this.ciphertextStream.reset();
    }
    
    @GuardedBy("this")
    private void disableRewinding() throws IOException {
        this.ciphertextStream.mark(0);
    }
    
    @Override
    public boolean markSupported() {
        return false;
    }
    
    @GuardedBy("this")
    @Override
    public synchronized int available() throws IOException {
        if (this.matchingStream == null) {
            return 0;
        }
        return this.matchingStream.available();
    }
    
    @GuardedBy("this")
    @Override
    public synchronized int read() throws IOException {
        final byte[] oneByte = { 0 };
        if (this.read(oneByte) == 1) {
            return oneByte[0] & 0xFF;
        }
        return -1;
    }
    
    @GuardedBy("this")
    @Override
    public synchronized int read(final byte[] b) throws IOException {
        return this.read(b, 0, b.length);
    }
    
    @GuardedBy("this")
    @Override
    public synchronized int read(final byte[] b, final int offset, final int len) throws IOException {
        if (len == 0) {
            return 0;
        }
        if (this.matchingStream != null) {
            return this.matchingStream.read(b, offset, len);
        }
        if (this.attemptedMatching) {
            throw new IOException("No matching key found for the ciphertext in the stream.");
        }
        this.attemptedMatching = true;
        for (final StreamingAead streamingAead : this.primitives) {
            try {
                final InputStream attemptedStream = streamingAead.newDecryptingStream(this.ciphertextStream, this.associatedData);
                final int retValue = attemptedStream.read(b, offset, len);
                if (retValue == 0) {
                    throw new IOException("Could not read bytes from the ciphertext stream");
                }
                this.matchingStream = attemptedStream;
                this.disableRewinding();
                return retValue;
            }
            catch (final IOException e) {
                this.rewind();
                continue;
            }
            catch (final GeneralSecurityException e2) {
                this.rewind();
                continue;
            }
            break;
        }
        throw new IOException("No matching key found for the ciphertext in the stream.");
    }
    
    @GuardedBy("this")
    @Override
    public synchronized void close() throws IOException {
        this.ciphertextStream.close();
    }
}
