package net.minecraft.world.level.dimension;

import net.minecraft.core.IRegistry;
import net.minecraft.core.IRegistryCustom$Dimension;
import net.minecraft.resources.MinecraftKey;
import net.minecraft.resources.ResourceKey;
import net.minecraft.server.MinecraftServer;
import net.minecraft.world.level.dimension.DimensionManager;
import net.minecraft.world.level.dimension.BuiltinDimensionTypes;

import com.bergerkiller.generated.net.minecraft.world.level.dimension.DimensionManagerHandle;

class DimensionManager {
    #bootstrap com.bergerkiller.bukkit.common.internal.CommonBootstrap.initServer();

#if version >= 1.14
    public boolean hasSkyLight();
#else
    // Fallback for versions before DimensionManager had this property
    // On these versions it is inside WorldProvider, but that one is annoying to use
    public boolean hasSkyLight() {
        return instance.getDimensionID() == 0;
    }
#endif

#if version >= 1.16
    #require net.minecraft.core.IRegistryCustom public static net.minecraft.core.IRegistry getDimensionTypeRegistry() {
        MinecraftServer server = MinecraftServer.getServer();

        // Get registry
        IRegistryCustom$Dimension registry;
  #if version >= 1.19.3
        registry = server.registryAccess();
  #elseif version >= 1.17
        registry = server.registryHolder;
  #elseif version >= 1.16.3
        registry = server.customRegistry;
  #else
        registry = server.f;
  #endif

        // Find the specific registry for dimension types
  #if version >= 1.21.2
        return registry.lookupOrThrow(net.minecraft.core.registries.Registries.DIMENSION_TYPE);
  #elseif version >= 1.19.3
        return registry.registryOrThrow(net.minecraft.core.registries.Registries.DIMENSION_TYPE);
  #elseif version >= 1.18
        return registry.ownedRegistryOrThrow(net.minecraft.core.IRegistry.DIMENSION_TYPE_REGISTRY);
  #elseif version >= 1.17
        return registry.b(net.minecraft.core.IRegistry.DIMENSION_TYPE_REGISTRY);
  #else
        return registry.a();
  #endif
    }

    public static Object getDimensionTypeRegistry() {
        return #getDimensionTypeRegistry();
    }

  #if version >= 1.19
    // deprecated fallback
    public int getId() {
        IRegistry dimensionTypeRegistry = #getDimensionTypeRegistry();
        java.util.Optional key_opt = dimensionTypeRegistry.getResourceKey((Object) instance);
        if (key_opt.isPresent()) {
            ResourceKey res_key = (ResourceKey) key_opt.get();
            if (res_key == BuiltinDimensionTypes.OVERWORLD) {
                return 0;
            } else if (res_key == BuiltinDimensionTypes.NETHER) {
                return -1;
            } else if (res_key == BuiltinDimensionTypes.END) {
                return 1;
            }
        }
        return 0;
    }

    public static (DimensionManagerHandle) DimensionManager fromId(int id) {
        ResourceKey res_key;
        if (id == 0) {
            res_key = BuiltinDimensionTypes.OVERWORLD;
        } else if (id == -1) {
            res_key = BuiltinDimensionTypes.NETHER;
        } else if (id == 1) {
            res_key = BuiltinDimensionTypes.END;
        } else {
            throw new IllegalArgumentException("Invalid dimension id " + id);
        }
        IRegistry dimensionTypeRegistry = #getDimensionTypeRegistry();
    #if version >= 1.21.2
        return (DimensionManager) dimensionTypeRegistry.getValue(res_key);
    #else
        return (DimensionManager) dimensionTypeRegistry.get(res_key);
    #endif
    }
  #elseif version >= 1.17
    // deprecated fallback
    public int getId() {
        IRegistry dimensionTypeRegistry = #getDimensionTypeRegistry();
    #if version >= 1.18
        java.util.Optional key_opt = dimensionTypeRegistry.getResourceKey((Object) instance);
    #else
        java.util.Optional key_opt = dimensionTypeRegistry.c((Object) instance);
    #endif
        if (key_opt.isPresent()) {
            ResourceKey res_key = (ResourceKey) key_opt.get();
            if (res_key == DimensionManager.OVERWORLD_LOCATION) {
                return 0;
            } else if (res_key == DimensionManager.NETHER_LOCATION) {
                return -1;
            } else if (res_key == DimensionManager.END_LOCATION) {
                return 1;
            }
        }
        return 0;
    }

    public static (DimensionManagerHandle) DimensionManager fromId(int id) {
        ResourceKey res_key;
        if (id == 0) {
            res_key = DimensionManager.OVERWORLD_LOCATION;
        } else if (id == -1) {
            res_key = DimensionManager.NETHER_LOCATION;
        } else if (id == 1) {
            res_key = DimensionManager.END_LOCATION;
        } else {
            throw new IllegalArgumentException("Invalid dimension id " + id);
        }
        IRegistry dimensionTypeRegistry = #getDimensionTypeRegistry();
    #if version >= 1.18
        return (DimensionManager) dimensionTypeRegistry.get(res_key);
    #else
        return (DimensionManager) dimensionTypeRegistry.a(res_key);
    #endif
    }
  #else
    // deprecated fallback
    public int getId() {
        IRegistry dimensionTypeRegistry = #getDimensionTypeRegistry();
        java.util.Optional key_opt = dimensionTypeRegistry.c((Object) instance);
        if (key_opt.isPresent()) {
            ResourceKey res_key = (ResourceKey) key_opt.get();
            if (res_key == DimensionManager.OVERWORLD) {
                return 0;
            } else if (res_key == DimensionManager.THE_NETHER) {
                return -1;
            } else if (res_key == DimensionManager.THE_END) {
                return 1;
            }
        }
        return 0;
    }

    public static (DimensionManagerHandle) DimensionManager fromId(int id) {
        ResourceKey res_key;
        if (id == 0) {
            res_key = DimensionManager.OVERWORLD;
        } else if (id == -1) {
            res_key = DimensionManager.THE_NETHER;
        } else if (id == 1) {
            res_key = DimensionManager.THE_END;
        } else {
            throw new IllegalArgumentException("Invalid dimension id " + id);
        }
        IRegistry dimensionTypeRegistry = #getDimensionTypeRegistry();
        return (DimensionManager) dimensionTypeRegistry.a(res_key);
    }
  #endif
#else
    // mapped to id on 1.15.2 and before
    public int getId:getDimensionID();
    public static (DimensionManagerHandle) DimensionManager fromId:a(int id);

    public static Object getDimensionTypeRegistry() {
        throw new IllegalStateException("Not supported");
    }
#endif
}
