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

package io.netty.handler.ssl;

import io.netty.buffer.ByteBufUtil;
import io.netty.util.internal.PlatformDependent;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufAllocator;
import io.netty.channel.Channel;
import io.netty.channel.AbstractCoalescingBufferQueue;

abstract class SslHandlerCoalescingBufferQueue extends AbstractCoalescingBufferQueue
{
    private final boolean wantsDirectBuffer;
    
    SslHandlerCoalescingBufferQueue(final Channel channel, final int initSize, final boolean wantsDirectBuffer) {
        super(channel, initSize);
        this.wantsDirectBuffer = wantsDirectBuffer;
    }
    
    protected abstract int wrapDataSize();
    
    @Override
    protected ByteBuf compose(final ByteBufAllocator alloc, final ByteBuf cumulation, final ByteBuf next) {
        return attemptCopyToCumulation(cumulation, next, this.wrapDataSize()) ? cumulation : this.copyAndCompose(alloc, cumulation, next);
    }
    
    @Override
    protected ByteBuf composeFirst(final ByteBufAllocator allocator, final ByteBuf first, final int bufferSize) {
        ByteBuf newFirst;
        if (this.wantsDirectBuffer) {
            newFirst = allocator.directBuffer(bufferSize);
        }
        else {
            newFirst = allocator.heapBuffer(bufferSize);
        }
        try {
            newFirst.writeBytes(first);
        }
        catch (final Throwable cause) {
            newFirst.release();
            PlatformDependent.throwException(cause);
        }
        assert !first.isReadable();
        first.release();
        return newFirst;
    }
    
    @Override
    protected ByteBuf removeEmptyValue() {
        return null;
    }
    
    private static boolean attemptCopyToCumulation(final ByteBuf cumulation, final ByteBuf next, final int wrapDataSize) {
        final int inReadableBytes = next.readableBytes();
        if (inReadableBytes == 0) {
            next.release();
            return true;
        }
        final int cumulationCapacity = cumulation.capacity();
        if (wrapDataSize - cumulation.readableBytes() >= inReadableBytes && ((cumulation.isWritable(inReadableBytes) && cumulationCapacity >= wrapDataSize) || (cumulationCapacity < wrapDataSize && ByteBufUtil.ensureWritableSuccess(cumulation.ensureWritable(inReadableBytes, false))))) {
            cumulation.writeBytes(next);
            next.release();
            return true;
        }
        return false;
    }
}
