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

package io.netty.handler.codec.quic;

import io.netty.channel.ChannelHandler;
import io.netty.util.internal.ObjectUtil;
import io.netty.util.internal.logging.InternalLogger;
import io.netty.channel.Channel;
import java.util.LinkedHashMap;
import java.util.HashMap;
import org.jetbrains.annotations.Nullable;
import io.netty.util.AttributeKey;
import io.netty.channel.ChannelOption;
import java.util.Map;

public final class Quic
{
    static final Map.Entry<ChannelOption<?>, Object>[] EMPTY_OPTION_ARRAY;
    static final Map.Entry<AttributeKey<?>, Object>[] EMPTY_ATTRIBUTE_ARRAY;
    static final int MAX_DATAGRAM_SIZE = 1350;
    static final int RESET_TOKEN_LEN = 16;
    private static final Throwable UNAVAILABILITY_CAUSE;
    public static final int MAX_CONN_ID_LEN = 20;
    
    public static boolean isVersionSupported(final int version) {
        return isAvailable() && Quiche.quiche_version_is_supported(version);
    }
    
    public static boolean isAvailable() {
        return Quic.UNAVAILABILITY_CAUSE == null;
    }
    
    public static void ensureAvailability() {
        if (Quic.UNAVAILABILITY_CAUSE != null) {
            throw (Error)new UnsatisfiedLinkError("failed to load the required native library").initCause(Quic.UNAVAILABILITY_CAUSE);
        }
    }
    
    @Nullable
    public static Throwable unavailabilityCause() {
        return Quic.UNAVAILABILITY_CAUSE;
    }
    
    static Map.Entry<ChannelOption<?>, Object>[] toOptionsArray(final Map<ChannelOption<?>, Object> opts) {
        return (Map.Entry[])new HashMap(opts).entrySet().toArray(Quic.EMPTY_OPTION_ARRAY);
    }
    
    static Map.Entry<AttributeKey<?>, Object>[] toAttributesArray(final Map<AttributeKey<?>, Object> attributes) {
        return (Map.Entry[])new LinkedHashMap(attributes).entrySet().toArray(Quic.EMPTY_ATTRIBUTE_ARRAY);
    }
    
    private static void setAttributes(final Channel channel, final Map.Entry<AttributeKey<?>, Object>[] attrs) {
        for (final Map.Entry<AttributeKey<?>, Object> e : attrs) {
            final AttributeKey<Object> key = e.getKey();
            channel.attr(key).set(e.getValue());
        }
    }
    
    private static void setChannelOptions(final Channel channel, final Map.Entry<ChannelOption<?>, Object>[] options, final InternalLogger logger) {
        for (final Map.Entry<ChannelOption<?>, Object> e : options) {
            setChannelOption(channel, e.getKey(), e.getValue(), logger);
        }
    }
    
    private static void setChannelOption(final Channel channel, final ChannelOption<?> option, final Object value, final InternalLogger logger) {
        try {
            if (!channel.config().setOption(option, value)) {
                logger.warn("Unknown channel option '{}' for channel '{}'", option, channel);
            }
        }
        catch (final Throwable t) {
            logger.warn("Failed to set channel option '{}' with value '{}' for channel '{}'", option, value, channel, t);
        }
    }
    
    static <T> void updateOptions(final Map<ChannelOption<?>, Object> options, final ChannelOption<T> option, @Nullable final T value) {
        ObjectUtil.checkNotNull(option, "option");
        if (value == null) {
            options.remove(option);
        }
        else {
            options.put(option, value);
        }
    }
    
    static <T> void updateAttributes(final Map<AttributeKey<?>, Object> attributes, final AttributeKey<T> key, @Nullable final T value) {
        ObjectUtil.checkNotNull(key, "key");
        if (value == null) {
            attributes.remove(key);
        }
        else {
            attributes.put(key, value);
        }
    }
    
    static void setupChannel(final Channel ch, final Map.Entry<ChannelOption<?>, Object>[] options, final Map.Entry<AttributeKey<?>, Object>[] attrs, @Nullable final ChannelHandler handler, final InternalLogger logger) {
        setChannelOptions(ch, options, logger);
        setAttributes(ch, attrs);
        if (handler != null) {
            ch.pipeline().addLast(handler);
        }
    }
    
    private Quic() {
    }
    
    static {
        EMPTY_OPTION_ARRAY = new Map.Entry[0];
        EMPTY_ATTRIBUTE_ARRAY = new Map.Entry[0];
        Throwable cause = null;
        try {
            final String version = Quiche.quiche_version();
            assert version != null;
        }
        catch (final Throwable error) {
            cause = error;
        }
        UNAVAILABILITY_CAUSE = cause;
    }
}
