package net.minecraft.server;

import org.apache.logging.log4j.LogManager;
import java.io.OutputStream;
import net.minecraft.world.entity.ai.attributes.DefaultAttributes;
import net.minecraft.SharedConstants;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.biome.Biome;
import net.minecraft.world.item.enchantment.Enchantment;
import net.minecraft.world.item.Item;
import net.minecraft.world.effect.MobEffect;
import net.minecraft.world.entity.ai.attributes.Attribute;
import java.util.TreeSet;
import net.minecraft.world.level.GameRules;
import net.minecraft.locale.Language;
import java.util.Set;
import java.util.function.Function;
import net.minecraft.commands.synchronization.ArgumentTypes;
import net.minecraft.core.dispenser.DispenseItemBehavior;
import net.minecraft.commands.arguments.selector.options.EntitySelectorOptions;
import net.minecraft.world.item.alchemy.PotionBrewing;
import net.minecraft.world.entity.EntityType;
import net.minecraft.world.level.block.ComposterBlock;
import net.minecraft.world.level.block.FireBlock;
import net.minecraft.core.Registry;
import org.apache.logging.log4j.Logger;
import java.io.PrintStream;

public class Bootstrap {
    public static final PrintStream STDOUT;
    private static boolean isBootstrapped;
    private static final Logger LOGGER;
    
    public static void bootStrap() {
        if (Bootstrap.isBootstrapped) {
            return;
        }
        Bootstrap.isBootstrapped = true;
        if (Registry.REGISTRY.keySet().isEmpty()) {
            throw new IllegalStateException("Unable to load registries");
        }
        FireBlock.bootStrap();
        ComposterBlock.bootStrap();
        if (EntityType.getKey(EntityType.PLAYER) == null) {
            throw new IllegalStateException("Failed loading EntityTypes");
        }
        PotionBrewing.bootStrap();
        EntitySelectorOptions.bootStrap();
        DispenseItemBehavior.bootStrap();
        ArgumentTypes.bootStrap();
        wrapStreams();
    }
    
    private static <T> void checkTranslations(final Iterable<T> iterable, final Function<T, String> function, final Set<String> set) {
        final Language kz4 = Language.getInstance();
        final String string5;
        final Language language;
        iterable.forEach(object -> {
            string5 = function.apply(object);
            if (!language.has(string5)) {
                set.add(string5);
            }
        });
    }
    
    private static void checkGameruleTranslations(final Set<String> set) {
        final Language kz2 = Language.getInstance();
        GameRules.visitGameRuleTypes(new GameRules.GameRuleTypeVisitor() {
            @Override
            public <T extends GameRules.Value<T>> void visit(final GameRules.Key<T> e, final GameRules.Type<T> f) {
                if (!kz2.has(e.getDescriptionId())) {
                    set.add(e.getId());
                }
            }
        });
    }
    
    public static Set<String> getMissingTranslations() {
        final Set<String> set1 = new TreeSet<String>();
        Bootstrap.<Attribute>checkTranslations(Registry.ATTRIBUTE, Attribute::getDescriptionId, set1);
        Bootstrap.<EntityType<?>>checkTranslations(Registry.ENTITY_TYPE, EntityType::getDescriptionId, set1);
        Bootstrap.<MobEffect>checkTranslations(Registry.MOB_EFFECT, MobEffect::getDescriptionId, set1);
        Bootstrap.<Item>checkTranslations(Registry.ITEM, Item::getDescriptionId, set1);
        Bootstrap.<Enchantment>checkTranslations(Registry.ENCHANTMENT, Enchantment::getDescriptionId, set1);
        Bootstrap.<Biome>checkTranslations(Registry.BIOME, Biome::getDescriptionId, set1);
        Bootstrap.<Block>checkTranslations(Registry.BLOCK, Block::getDescriptionId, set1);
        Bootstrap.<ResourceLocation>checkTranslations((Iterable<ResourceLocation>)Registry.CUSTOM_STAT, uh -> "stat." + uh.toString().replace(':', '.'), set1);
        checkGameruleTranslations(set1);
        return set1;
    }
    
    public static void validate() {
        if (!Bootstrap.isBootstrapped) {
            throw new IllegalArgumentException("Not bootstrapped");
        }
        if (SharedConstants.IS_RUNNING_IN_IDE) {
            getMissingTranslations().forEach(string -> Bootstrap.LOGGER.error("Missing translations: " + string));
        }
        DefaultAttributes.validate();
    }
    
    private static void wrapStreams() {
        if (Bootstrap.LOGGER.isDebugEnabled()) {
            System.setErr(new DebugLoggedPrintStream("STDERR", System.err));
            System.setOut(new DebugLoggedPrintStream("STDOUT", Bootstrap.STDOUT));
        }
        else {
            System.setErr(new LoggedPrintStream("STDERR", System.err));
            System.setOut(new LoggedPrintStream("STDOUT", Bootstrap.STDOUT));
        }
    }
    
    public static void realStdoutPrintln(final String string) {
        Bootstrap.STDOUT.println(string);
    }
    
    static {
        STDOUT = System.out;
        LOGGER = LogManager.getLogger();
    }
}
