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

package io.netty.handler.codec.http3;

import io.netty.channel.socket.ChannelInputShutdownReadComplete;
import io.netty.handler.codec.http.HttpMethod;
import io.netty.channel.ChannelPromise;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelHandler;
import java.util.function.BooleanSupplier;

final class Http3RequestStreamValidationHandler extends Http3FrameTypeDuplexValidationHandler<Http3RequestStreamFrame>
{
    private final boolean server;
    private final BooleanSupplier goAwayReceivedSupplier;
    private final QpackAttributes qpackAttributes;
    private final QpackDecoder qpackDecoder;
    private final Http3RequestStreamCodecState decodeState;
    private final Http3RequestStreamCodecState encodeState;
    private boolean clientHeadRequest;
    private long expectedLength;
    private long seenLength;
    
    static ChannelHandler newServerValidator(final QpackAttributes qpackAttributes, final QpackDecoder decoder, final Http3RequestStreamCodecState encodeState, final Http3RequestStreamCodecState decodeState) {
        return new Http3RequestStreamValidationHandler(true, () -> false, qpackAttributes, decoder, encodeState, decodeState);
    }
    
    static ChannelHandler newClientValidator(final BooleanSupplier goAwayReceivedSupplier, final QpackAttributes qpackAttributes, final QpackDecoder decoder, final Http3RequestStreamCodecState encodeState, final Http3RequestStreamCodecState decodeState) {
        return new Http3RequestStreamValidationHandler(false, goAwayReceivedSupplier, qpackAttributes, decoder, encodeState, decodeState);
    }
    
    private Http3RequestStreamValidationHandler(final boolean server, final BooleanSupplier goAwayReceivedSupplier, final QpackAttributes qpackAttributes, final QpackDecoder qpackDecoder, final Http3RequestStreamCodecState encodeState, final Http3RequestStreamCodecState decodeState) {
        super(Http3RequestStreamFrame.class);
        this.expectedLength = -1L;
        this.server = server;
        this.goAwayReceivedSupplier = goAwayReceivedSupplier;
        this.qpackAttributes = qpackAttributes;
        this.qpackDecoder = qpackDecoder;
        this.decodeState = decodeState;
        this.encodeState = encodeState;
    }
    
    @Override
    void write(final ChannelHandlerContext ctx, final Http3RequestStreamFrame frame, final ChannelPromise promise) {
        if (!this.server) {
            if (!Http3RequestStreamValidationUtils.validateClientWrite(frame, promise, ctx, this.goAwayReceivedSupplier, this.encodeState)) {
                return;
            }
            if (frame instanceof Http3HeadersFrame) {
                this.clientHeadRequest = HttpMethod.HEAD.asciiName().equals(((Http3HeadersFrame)frame).headers().method());
            }
        }
        ctx.write(frame, promise);
    }
    
    @Override
    void channelRead(final ChannelHandlerContext ctx, final Http3RequestStreamFrame frame) {
        if (frame instanceof Http3PushPromiseFrame) {
            if (this.server) {
                Http3FrameValidationUtils.frameTypeUnexpected(ctx, frame);
            }
            else {
                ctx.fireChannelRead((Object)frame);
            }
            return;
        }
        if (frame instanceof Http3HeadersFrame) {
            final Http3HeadersFrame headersFrame = (Http3HeadersFrame)frame;
            final long maybeContentLength = Http3RequestStreamValidationUtils.validateHeaderFrameRead(headersFrame, ctx, this.decodeState);
            if (maybeContentLength >= 0L) {
                this.expectedLength = maybeContentLength;
            }
            else if (maybeContentLength == -2L) {
                return;
            }
        }
        if (frame instanceof Http3DataFrame) {
            final Http3DataFrame dataFrame = (Http3DataFrame)frame;
            final long maybeContentLength = Http3RequestStreamValidationUtils.validateDataFrameRead(dataFrame, ctx, this.expectedLength, this.seenLength, this.clientHeadRequest);
            if (maybeContentLength >= 0L) {
                this.seenLength = maybeContentLength;
            }
            else if (maybeContentLength == -2L) {
                return;
            }
        }
        ctx.fireChannelRead((Object)frame);
    }
    
    @Override
    public void userEventTriggered(final ChannelHandlerContext ctx, final Object evt) {
        if (evt == ChannelInputShutdownReadComplete.INSTANCE) {
            Http3RequestStreamValidationUtils.sendStreamAbandonedIfRequired(ctx, this.qpackAttributes, this.qpackDecoder, this.decodeState);
            if (!Http3RequestStreamValidationUtils.validateOnStreamClosure(ctx, this.expectedLength, this.seenLength, this.clientHeadRequest)) {
                return;
            }
        }
        ctx.fireUserEventTriggered(evt);
    }
    
    @Override
    public boolean isSharable() {
        return false;
    }
}
