package net.minecraft.server.packs.resources;

import com.google.common.base.Stopwatch;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Executor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicLong;
import net.minecraft.SystemUtils;
import net.minecraft.util.Unit;
import net.minecraft.util.profiling.MethodProfiler;
import net.minecraft.util.profiling.MethodProfilerResults;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

public class ReloadableProfiled extends Reloadable<ReloadableProfiled.a> {

    private static final Logger LOGGER = LogManager.getLogger();
    private final Stopwatch total = Stopwatch.createUnstarted();

    public ReloadableProfiled(IResourceManager iresourcemanager, List<IReloadListener> list, Executor executor, Executor executor1, CompletableFuture<Unit> completablefuture) {
        super(executor, executor1, iresourcemanager, list, (ireloadlistener_a, iresourcemanager1, ireloadlistener, executor2, executor3) -> {
            AtomicLong atomiclong = new AtomicLong();
            AtomicLong atomiclong1 = new AtomicLong();
            MethodProfiler methodprofiler = new MethodProfiler(SystemUtils.timeSource, () -> {
                return 0;
            }, false);
            MethodProfiler methodprofiler1 = new MethodProfiler(SystemUtils.timeSource, () -> {
                return 0;
            }, false);
            CompletableFuture<Void> completablefuture1 = ireloadlistener.a(ireloadlistener_a, iresourcemanager1, methodprofiler, methodprofiler1, (runnable) -> {
                executor2.execute(() -> {
                    long i = SystemUtils.getMonotonicNanos();

                    runnable.run();
                    atomiclong.addAndGet(SystemUtils.getMonotonicNanos() - i);
                });
            }, (runnable) -> {
                executor3.execute(() -> {
                    long i = SystemUtils.getMonotonicNanos();

                    runnable.run();
                    atomiclong1.addAndGet(SystemUtils.getMonotonicNanos() - i);
                });
            });

            return completablefuture1.thenApplyAsync((ovoid) -> {
                return new ReloadableProfiled.a(ireloadlistener.c(), methodprofiler.d(), methodprofiler1.d(), atomiclong, atomiclong1);
            }, executor1);
        }, completablefuture);
        this.total.start();
        this.allDone.thenAcceptAsync(this::a, executor1);
    }

    private void a(List<ReloadableProfiled.a> list) {
        this.total.stop();
        int i = 0;

        ReloadableProfiled.LOGGER.info("Resource reload finished after {} ms", this.total.elapsed(TimeUnit.MILLISECONDS));

        int j;

        for (Iterator iterator = list.iterator(); iterator.hasNext(); i += j) {
            ReloadableProfiled.a reloadableprofiled_a = (ReloadableProfiled.a) iterator.next();
            MethodProfilerResults methodprofilerresults = reloadableprofiled_a.preparationResult;
            MethodProfilerResults methodprofilerresults1 = reloadableprofiled_a.reloadResult;
            int k = (int) ((double) reloadableprofiled_a.preparationNanos.get() / 1000000.0D);

            j = (int) ((double) reloadableprofiled_a.reloadNanos.get() / 1000000.0D);
            int l = k + j;
            String s = reloadableprofiled_a.name;

            ReloadableProfiled.LOGGER.info("{} took approximately {} ms ({} ms preparing, {} ms applying)", s, l, k, j);
        }

        ReloadableProfiled.LOGGER.info("Total blocking time: {} ms", i);
    }

    public static class a {

        final String name;
        final MethodProfilerResults preparationResult;
        final MethodProfilerResults reloadResult;
        final AtomicLong preparationNanos;
        final AtomicLong reloadNanos;

        a(String s, MethodProfilerResults methodprofilerresults, MethodProfilerResults methodprofilerresults1, AtomicLong atomiclong, AtomicLong atomiclong1) {
            this.name = s;
            this.preparationResult = methodprofilerresults;
            this.reloadResult = methodprofilerresults1;
            this.preparationNanos = atomiclong;
            this.reloadNanos = atomiclong1;
        }
    }
}
