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

package io.netty.handler.codec.quic;

import java.util.concurrent.Executor;
import java.util.function.Function;
import io.netty.util.internal.ObjectUtil;
import org.jetbrains.annotations.Nullable;
import java.util.HashMap;
import java.util.LinkedHashMap;
import io.netty.channel.ChannelHandler;
import io.netty.util.AttributeKey;
import io.netty.channel.ChannelOption;
import java.util.Map;

public final class QuicServerCodecBuilder extends QuicCodecBuilder<QuicServerCodecBuilder>
{
    private final Map<ChannelOption<?>, Object> options;
    private final Map<AttributeKey<?>, Object> attrs;
    private final Map<ChannelOption<?>, Object> streamOptions;
    private final Map<AttributeKey<?>, Object> streamAttrs;
    private ChannelHandler handler;
    private ChannelHandler streamHandler;
    private QuicConnectionIdGenerator connectionIdAddressGenerator;
    private QuicTokenHandler tokenHandler;
    private QuicResetTokenGenerator resetTokenGenerator;
    
    public QuicServerCodecBuilder() {
        super(true);
        this.options = new LinkedHashMap<ChannelOption<?>, Object>();
        this.attrs = new HashMap<AttributeKey<?>, Object>();
        this.streamOptions = new LinkedHashMap<ChannelOption<?>, Object>();
        this.streamAttrs = new HashMap<AttributeKey<?>, Object>();
    }
    
    private QuicServerCodecBuilder(final QuicServerCodecBuilder builder) {
        super(builder);
        this.options = new LinkedHashMap<ChannelOption<?>, Object>();
        this.attrs = new HashMap<AttributeKey<?>, Object>();
        this.streamOptions = new LinkedHashMap<ChannelOption<?>, Object>();
        this.streamAttrs = new HashMap<AttributeKey<?>, Object>();
        this.options.putAll(builder.options);
        this.attrs.putAll(builder.attrs);
        this.streamOptions.putAll(builder.streamOptions);
        this.streamAttrs.putAll(builder.streamAttrs);
        this.handler = builder.handler;
        this.streamHandler = builder.streamHandler;
        this.connectionIdAddressGenerator = builder.connectionIdAddressGenerator;
        this.tokenHandler = builder.tokenHandler;
        this.resetTokenGenerator = builder.resetTokenGenerator;
    }
    
    @Override
    public QuicServerCodecBuilder clone() {
        return new QuicServerCodecBuilder(this);
    }
    
    public <T> QuicServerCodecBuilder option(final ChannelOption<T> option, @Nullable final T value) {
        Quic.updateOptions(this.options, option, value);
        return this.self();
    }
    
    public <T> QuicServerCodecBuilder attr(final AttributeKey<T> key, @Nullable final T value) {
        Quic.updateAttributes(this.attrs, key, value);
        return this.self();
    }
    
    public QuicServerCodecBuilder handler(final ChannelHandler handler) {
        this.handler = ObjectUtil.checkNotNull(handler, "handler");
        return this.self();
    }
    
    public <T> QuicServerCodecBuilder streamOption(final ChannelOption<T> option, @Nullable final T value) {
        Quic.updateOptions(this.streamOptions, option, value);
        return this.self();
    }
    
    public <T> QuicServerCodecBuilder streamAttr(final AttributeKey<T> key, @Nullable final T value) {
        Quic.updateAttributes(this.streamAttrs, key, value);
        return this.self();
    }
    
    public QuicServerCodecBuilder streamHandler(final ChannelHandler streamHandler) {
        this.streamHandler = ObjectUtil.checkNotNull(streamHandler, "streamHandler");
        return this.self();
    }
    
    public QuicServerCodecBuilder connectionIdAddressGenerator(final QuicConnectionIdGenerator connectionIdAddressGenerator) {
        this.connectionIdAddressGenerator = connectionIdAddressGenerator;
        return this;
    }
    
    public QuicServerCodecBuilder tokenHandler(@Nullable final QuicTokenHandler tokenHandler) {
        this.tokenHandler = tokenHandler;
        return this.self();
    }
    
    public QuicServerCodecBuilder resetTokenGenerator(@Nullable final QuicResetTokenGenerator resetTokenGenerator) {
        this.resetTokenGenerator = resetTokenGenerator;
        return this.self();
    }
    
    @Override
    protected void validate() {
        super.validate();
        if (this.handler == null && this.streamHandler == null) {
            throw new IllegalStateException("handler and streamHandler not set");
        }
    }
    
    @Override
    ChannelHandler build(final QuicheConfig config, final Function<QuicChannel, ? extends QuicSslEngine> sslEngineProvider, final Executor sslTaskExecutor, final int localConnIdLength, final FlushStrategy flushStrategy) {
        this.validate();
        QuicTokenHandler tokenHandler = this.tokenHandler;
        if (tokenHandler == null) {
            tokenHandler = NoQuicTokenHandler.INSTANCE;
        }
        QuicConnectionIdGenerator generator = this.connectionIdAddressGenerator;
        if (generator == null) {
            generator = QuicConnectionIdGenerator.signGenerator();
        }
        QuicResetTokenGenerator resetTokenGenerator = this.resetTokenGenerator;
        if (resetTokenGenerator == null) {
            resetTokenGenerator = QuicResetTokenGenerator.signGenerator();
        }
        final ChannelHandler handler = this.handler;
        final ChannelHandler streamHandler = this.streamHandler;
        return new QuicheQuicServerCodec(config, localConnIdLength, tokenHandler, generator, resetTokenGenerator, flushStrategy, sslEngineProvider, sslTaskExecutor, handler, Quic.toOptionsArray(this.options), Quic.toAttributesArray(this.attrs), streamHandler, Quic.toOptionsArray(this.streamOptions), Quic.toAttributesArray(this.streamAttrs));
    }
}
