package net.minecraft.client.gui.font;

import org.apache.logging.log4j.LogManager;
import net.minecraft.client.gui.Font;
import net.minecraft.Util;
import java.util.function.Consumer;
import it.unimi.dsi.fastutil.ints.IntSet;
import com.google.gson.JsonArray;
import java.io.InputStream;
import java.util.Iterator;
import com.google.gson.Gson;
import it.unimi.dsi.fastutil.ints.IntCollection;
import it.unimi.dsi.fastutil.ints.IntOpenHashSet;
import java.io.IOException;
import net.minecraft.client.gui.font.providers.GlyphProviderBuilderType;
import net.minecraft.util.GsonHelper;
import com.google.gson.JsonObject;
import java.io.Reader;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import net.minecraft.server.packs.resources.Resource;
import com.google.common.collect.Lists;
import com.google.gson.GsonBuilder;
import net.minecraft.util.profiling.ProfilerFiller;
import net.minecraft.server.packs.resources.ResourceManager;
import com.mojang.blaze3d.font.GlyphProvider;
import java.util.List;
import net.minecraft.server.packs.resources.SimplePreparableReloadListener;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Maps;
import net.minecraft.server.packs.resources.PreparableReloadListener;
import net.minecraft.client.renderer.texture.TextureManager;
import java.util.Map;
import net.minecraft.resources.ResourceLocation;
import org.apache.logging.log4j.Logger;

public class FontManager implements AutoCloseable {
    private static final Logger LOGGER;
    public static final ResourceLocation MISSING_FONT;
    private final FontSet missingFontSet;
    private final Map<ResourceLocation, FontSet> fontSets;
    private final TextureManager textureManager;
    private Map<ResourceLocation, ResourceLocation> renames;
    private final PreparableReloadListener reloadListener;
    
    public FontManager(final TextureManager elw) {
        this.fontSets = Maps.newHashMap();
        this.renames = ImmutableMap.of();
        this.reloadListener = new SimplePreparableReloadListener<Map<ResourceLocation, List<GlyphProvider>>>() {
            @Override
            protected Map<ResourceLocation, List<GlyphProvider>> prepare(final ResourceManager abc, final ProfilerFiller ami) {
                ami.startTick();
                final Gson gson4 = new GsonBuilder().setPrettyPrinting().disableHtmlEscaping().create();
                final Map<ResourceLocation, List<GlyphProvider>> map5 = Maps.newHashMap();
                for (final ResourceLocation uh7 : abc.listResources("font", string -> string.endsWith(".json"))) {
                    final String string2 = uh7.getPath();
                    final ResourceLocation uh8 = new ResourceLocation(uh7.getNamespace(), string2.substring("font/".length(), string2.length() - ".json".length()));
                    final List<GlyphProvider> list10 = map5.computeIfAbsent(uh8, uh -> Lists.<GlyphProvider>newArrayList(new AllMissingGlyphProvider()));
                    ami.push(uh8::toString);
                    try {
                        for (final Resource abb12 : abc.getResources(uh7)) {
                            ami.push(abb12::getSourceName);
                            try (final InputStream inputStream13 = abb12.getInputStream();
                                 final Reader reader15 = new BufferedReader(new InputStreamReader(inputStream13, StandardCharsets.UTF_8))) {
                                ami.push("reading");
                                final JsonArray jsonArray17 = GsonHelper.getAsJsonArray(GsonHelper.<JsonObject>fromJson(gson4, reader15, JsonObject.class), "providers");
                                ami.popPush("parsing");
                                for (int integer2 = jsonArray17.size() - 1; integer2 >= 0; --integer2) {
                                    final JsonObject jsonObject19 = GsonHelper.convertToJsonObject(jsonArray17.get(integer2), "providers[" + integer2 + "]");
                                    try {
                                        final String string3 = GsonHelper.getAsString(jsonObject19, "type");
                                        final GlyphProviderBuilderType dpe21 = GlyphProviderBuilderType.byName(string3);
                                        ami.push(string3);
                                        final GlyphProvider dga22 = dpe21.create(jsonObject19).create(abc);
                                        if (dga22 != null) {
                                            list10.add(dga22);
                                        }
                                        ami.pop();
                                    }
                                    catch (RuntimeException runtimeException20) {
                                        FontManager.LOGGER.warn("Unable to read definition '{}' in fonts.json in resourcepack: '{}': {}", uh8, abb12.getSourceName(), runtimeException20.getMessage());
                                    }
                                }
                                ami.pop();
                            }
                            catch (RuntimeException runtimeException21) {
                                FontManager.LOGGER.warn("Unable to load font '{}' in fonts.json in resourcepack: '{}': {}", uh8, abb12.getSourceName(), runtimeException21.getMessage());
                            }
                            ami.pop();
                        }
                    }
                    catch (IOException iOException11) {
                        FontManager.LOGGER.warn("Unable to load font '{}' in fonts.json: {}", uh8, iOException11.getMessage());
                    }
                    ami.push("caching");
                    final IntSet intSet11 = (IntSet)new IntOpenHashSet();
                    for (final GlyphProvider dga23 : list10) {
                        intSet11.addAll((IntCollection)dga23.getSupportedGlyphs());
                    }
                    final List<GlyphProvider> list11;
                    final Iterator<GlyphProvider> iterator4;
                    GlyphProvider dga24;
                    intSet11.forEach(integer -> {
                        if (integer == 32) {
                            return;
                        }
                        else {
                            Lists.<GlyphProvider>reverse(list11).iterator();
                            while (iterator4.hasNext()) {
                                dga24 = iterator4.next();
                                if (dga24.getGlyph(integer) != null) {
                                    break;
                                }
                            }
                            return;
                        }
                    });
                    ami.pop();
                    ami.pop();
                }
                ami.endTick();
                return map5;
            }
            
            @Override
            protected void apply(final Map<ResourceLocation, List<GlyphProvider>> map, final ResourceManager abc, final ProfilerFiller ami) {
                ami.startTick();
                ami.push("closing");
                FontManager.this.fontSets.values().forEach(FontSet::close);
                FontManager.this.fontSets.clear();
                ami.popPush("reloading");
                final FontSet dot4;
                map.forEach((uh, list) -> {
                    dot4 = new FontSet(FontManager.this.textureManager, uh);
                    dot4.reload(Lists.<GlyphProvider>reverse(list));
                    FontManager.this.fontSets.put(uh, dot4);
                    return;
                });
                ami.pop();
                ami.endTick();
            }
            
            @Override
            public String getName() {
                return "FontManager";
            }
        };
        this.textureManager = elw;
        this.missingFontSet = Util.<FontSet>make(new FontSet(elw, FontManager.MISSING_FONT), dot -> dot.reload(Lists.<GlyphProvider>newArrayList(new AllMissingGlyphProvider())));
    }
    
    public void setRenames(final Map<ResourceLocation, ResourceLocation> map) {
        this.renames = map;
    }
    
    public Font createFont() {
        return new Font(uh -> this.fontSets.getOrDefault(this.renames.getOrDefault(uh, uh), this.missingFontSet));
    }
    
    public PreparableReloadListener getReloadListener() {
        return this.reloadListener;
    }
    
    @Override
    public void close() {
        this.fontSets.values().forEach(FontSet::close);
        this.missingFontSet.close();
    }
    
    static {
        LOGGER = LogManager.getLogger();
        MISSING_FONT = new ResourceLocation("minecraft", "missing");
    }
}
