package net.minecraft.util;

import com.google.common.util.concurrent.MoreExecutors;
import java.util.concurrent.Executors;
import net.minecraft.DefaultUncaughtExceptionHandler;
import com.google.common.util.concurrent.ThreadFactoryBuilder;
import org.apache.logging.log4j.LogManager;
import java.net.ServerSocket;
import java.util.Iterator;
import java.io.InputStream;
import java.util.concurrent.Executor;
import org.apache.commons.io.IOUtils;
import java.io.IOException;
import java.io.OutputStream;
import java.io.FileOutputStream;
import java.io.DataOutputStream;
import org.apache.commons.io.FileUtils;
import java.util.Locale;
import java.net.HttpURLConnection;
import java.net.URL;
import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.TranslatableComponent;
import java.util.concurrent.CompletableFuture;
import java.net.Proxy;
import javax.annotation.Nullable;
import java.util.Map;
import java.io.File;
import com.google.common.util.concurrent.ListeningExecutorService;
import org.apache.logging.log4j.Logger;

public class HttpUtil {
    private static final Logger LOGGER;
    public static final ListeningExecutorService DOWNLOAD_EXECUTOR;
    
    public static CompletableFuture<?> downloadTo(final File file, final String string, final Map<String, String> map, final int integer, @Nullable final ProgressListener abs, final Proxy proxy) {
        HttpURLConnection httpURLConnection7;
        InputStream inputStream8;
        OutputStream outputStream9;
        byte[] arr10;
        URL uRL11;
        float float12;
        float float13;
        final Iterator<Map.Entry<String, String>> iterator;
        Map.Entry<String, String> entry15;
        final float n;
        float float14;
        int integer2;
        final TranslatableComponent lf;
        long long15;
        final DataOutputStream dataOutputStream;
        final IOException ex;
        int integer3;
        final IOException ex2;
        InputStream inputStream9;
        return CompletableFuture.supplyAsync(() -> {
            httpURLConnection7 = null;
            inputStream8 = null;
            outputStream9 = null;
            if (abs != null) {
                abs.progressStart(new TranslatableComponent("resourcepack.downloading", new Object[0]));
                abs.progressStage(new TranslatableComponent("resourcepack.requesting", new Object[0]));
            }
            try {
                arr10 = new byte[4096];
                uRL11 = new URL(string);
                httpURLConnection7 = (HttpURLConnection)uRL11.openConnection(proxy);
                httpURLConnection7.setInstanceFollowRedirects(true);
                float12 = 0.0f;
                float13 = (float)map.entrySet().size();
                map.entrySet().iterator();
                while (iterator.hasNext()) {
                    entry15 = iterator.next();
                    httpURLConnection7.setRequestProperty(entry15.getKey(), entry15.getValue());
                    if (abs != null) {
                        ++float12;
                        abs.progressStagePercentage((int)(n / float13 * 100.0f));
                    }
                }
                inputStream8 = httpURLConnection7.getInputStream();
                float14 = (float)httpURLConnection7.getContentLength();
                integer2 = httpURLConnection7.getContentLength();
                if (abs != null) {
                    new TranslatableComponent("resourcepack.progress", new Object[] { String.format(Locale.ROOT, "%.2f", float14 / 1000.0f / 1000.0f) });
                    abs.progressStage(lf);
                }
                if (file.exists()) {
                    long15 = file.length();
                    if (long15 == integer2) {
                        if (abs != null) {
                            abs.stop();
                        }
                        return null;
                    }
                    else {
                        HttpUtil.LOGGER.warn("Deleting {} as it does not match what we currently have ({} vs our {}).", file, integer2, long15);
                        FileUtils.deleteQuietly(file);
                    }
                }
                else if (file.getParentFile() != null) {
                    file.getParentFile().mkdirs();
                }
                new DataOutputStream(new FileOutputStream(file));
                outputStream9 = dataOutputStream;
                if (integer > 0 && float14 > integer) {
                    if (abs != null) {
                        abs.stop();
                    }
                    new IOException("Filesize is bigger than maximum allowed (file is " + float12 + ", limit is " + integer + ")");
                    throw ex;
                }
                else {
                    while ((integer3 = inputStream8.read(arr10)) >= 0) {
                        float12 += integer3;
                        if (abs != null) {
                            abs.progressStagePercentage((int)(float12 / float14 * 100.0f));
                        }
                        if (integer > 0 && float12 > integer) {
                            if (abs != null) {
                                abs.stop();
                            }
                            new IOException("Filesize was bigger than maximum allowed (got >= " + float12 + ", limit was " + integer + ")");
                            throw ex2;
                        }
                        else if (Thread.interrupted()) {
                            HttpUtil.LOGGER.error("INTERRUPTED");
                            if (abs != null) {
                                abs.stop();
                            }
                            return null;
                        }
                        else {
                            outputStream9.write(arr10, 0, integer3);
                        }
                    }
                    if (abs != null) {
                        abs.stop();
                    }
                }
            }
            catch (Throwable throwable10) {
                throwable10.printStackTrace();
                if (httpURLConnection7 != null) {
                    inputStream9 = httpURLConnection7.getErrorStream();
                    try {
                        HttpUtil.LOGGER.error(IOUtils.toString(inputStream9));
                    }
                    catch (IOException iOException12) {
                        iOException12.printStackTrace();
                    }
                }
                if (abs != null) {
                    abs.stop();
                }
            }
            finally {
                IOUtils.closeQuietly(inputStream8);
                IOUtils.closeQuietly(outputStream9);
            }
            return null;
        }, HttpUtil.DOWNLOAD_EXECUTOR);
    }
    
    public static int getAvailablePort() {
        try (final ServerSocket serverSocket1 = new ServerSocket(0)) {
            return serverSocket1.getLocalPort();
        }
        catch (IOException iOException1) {
            return 25564;
        }
    }
    
    static {
        LOGGER = LogManager.getLogger();
        DOWNLOAD_EXECUTOR = MoreExecutors.listeningDecorator(Executors.newCachedThreadPool(new ThreadFactoryBuilder().setDaemon(true).setUncaughtExceptionHandler(new DefaultUncaughtExceptionHandler(HttpUtil.LOGGER)).setNameFormat("Downloader %d").build()));
    }
}
