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

package io.netty.resolver;

import io.netty.util.internal.SystemPropertyUtil;
import io.netty.util.internal.logging.InternalLoggerFactory;
import io.netty.util.CharsetUtil;
import java.nio.charset.Charset;
import io.netty.util.internal.PlatformDependent;
import java.util.Collection;
import java.util.ArrayList;
import java.util.Locale;
import io.netty.util.internal.ObjectUtil;
import java.net.InetAddress;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicLong;
import io.netty.util.internal.logging.InternalLogger;

public final class DefaultHostsFileEntriesResolver implements HostsFileEntriesResolver
{
    private static final InternalLogger logger;
    private static final long DEFAULT_REFRESH_INTERVAL;
    private final long refreshInterval;
    private final AtomicLong lastRefresh;
    private final HostsFileEntriesProvider.Parser hostsFileParser;
    private volatile Map<String, List<InetAddress>> inet4Entries;
    private volatile Map<String, List<InetAddress>> inet6Entries;
    
    public DefaultHostsFileEntriesResolver() {
        this(HostsFileEntriesProvider.parser(), DefaultHostsFileEntriesResolver.DEFAULT_REFRESH_INTERVAL);
    }
    
    DefaultHostsFileEntriesResolver(final HostsFileEntriesProvider.Parser hostsFileParser, final long refreshInterval) {
        this.lastRefresh = new AtomicLong(System.nanoTime());
        this.hostsFileParser = hostsFileParser;
        this.refreshInterval = ObjectUtil.checkPositiveOrZero(refreshInterval, "refreshInterval");
        final HostsFileEntriesProvider entries = parseEntries(hostsFileParser);
        this.inet4Entries = entries.ipv4Entries();
        this.inet6Entries = entries.ipv6Entries();
    }
    
    @Override
    public InetAddress address(final String inetHost, final ResolvedAddressTypes resolvedAddressTypes) {
        return firstAddress(this.addresses(inetHost, resolvedAddressTypes));
    }
    
    public List<InetAddress> addresses(final String inetHost, final ResolvedAddressTypes resolvedAddressTypes) {
        final String normalized = this.normalize(inetHost);
        this.ensureHostsFileEntriesAreFresh();
        switch (resolvedAddressTypes) {
            case IPV4_ONLY: {
                return this.inet4Entries.get(normalized);
            }
            case IPV6_ONLY: {
                return this.inet6Entries.get(normalized);
            }
            case IPV4_PREFERRED: {
                final List<InetAddress> allInet4Addresses = this.inet4Entries.get(normalized);
                return (allInet4Addresses != null) ? allAddresses(allInet4Addresses, this.inet6Entries.get(normalized)) : this.inet6Entries.get(normalized);
            }
            case IPV6_PREFERRED: {
                final List<InetAddress> allInet6Addresses = this.inet6Entries.get(normalized);
                return (allInet6Addresses != null) ? allAddresses(allInet6Addresses, this.inet4Entries.get(normalized)) : this.inet4Entries.get(normalized);
            }
            default: {
                throw new IllegalArgumentException("Unknown ResolvedAddressTypes " + resolvedAddressTypes);
            }
        }
    }
    
    private void ensureHostsFileEntriesAreFresh() {
        final long interval = this.refreshInterval;
        if (interval == 0L) {
            return;
        }
        final long last = this.lastRefresh.get();
        final long currentTime = System.nanoTime();
        if (currentTime - last > interval && this.lastRefresh.compareAndSet(last, currentTime)) {
            final HostsFileEntriesProvider entries = parseEntries(this.hostsFileParser);
            this.inet4Entries = entries.ipv4Entries();
            this.inet6Entries = entries.ipv6Entries();
        }
    }
    
    String normalize(final String inetHost) {
        return inetHost.toLowerCase(Locale.ENGLISH);
    }
    
    private static List<InetAddress> allAddresses(final List<InetAddress> a, final List<InetAddress> b) {
        final List<InetAddress> result = new ArrayList<InetAddress>(a.size() + ((b == null) ? 0 : b.size()));
        result.addAll(a);
        if (b != null) {
            result.addAll(b);
        }
        return result;
    }
    
    private static InetAddress firstAddress(final List<InetAddress> addresses) {
        return (addresses != null && !addresses.isEmpty()) ? addresses.get(0) : null;
    }
    
    private static HostsFileEntriesProvider parseEntries(final HostsFileEntriesProvider.Parser parser) {
        if (PlatformDependent.isWindows()) {
            return parser.parseSilently(Charset.defaultCharset(), CharsetUtil.UTF_16, CharsetUtil.UTF_8);
        }
        return parser.parseSilently();
    }
    
    static {
        logger = InternalLoggerFactory.getInstance(DefaultHostsFileEntriesResolver.class);
        DEFAULT_REFRESH_INTERVAL = SystemPropertyUtil.getLong("io.netty.hostsFileRefreshInterval", 0L);
        if (DefaultHostsFileEntriesResolver.logger.isDebugEnabled()) {
            DefaultHostsFileEntriesResolver.logger.debug("-Dio.netty.hostsFileRefreshInterval: {}", (Object)DefaultHostsFileEntriesResolver.DEFAULT_REFRESH_INTERVAL);
        }
    }
}
