package me.km.world;

import java.util.ArrayList;
import me.km.KajetansMod;
import me.km.utils.ReflectionUtils;
import net.minecraft.server.MinecraftServer;
import net.minecraft.util.ResourceLocation;
import net.minecraft.world.IWorld;
import net.minecraft.world.dimension.DimensionType;
import net.minecraft.world.server.ServerWorld;
import net.minecraftforge.common.DimensionManager;
import net.minecraftforge.common.ModDimension;
import net.minecraftforge.registries.ClearableRegistry;

public class WorldManager {
    public static final ModDimension MOD_DIMENSION = new ModDimensionFactory().setRegistryName(KajetansMod.MODID, "mod_dimension");

    // -------------------------------------------------------------------------
    // unsafe stuff
    // -------------------------------------------------------------------------
    private static ResourceLocation getRegistry(DimensionType type) {
        ResourceLocation rl = type.getRegistryName();
        if(rl != null) {
            return rl;
        }
        rl = DimensionManager.getRegistry().getKey(type);
        if(rl == null) {
            return null;
        }
        type.setRegistryName(rl);
        return rl;
    }

    private static DimensionType getDimensionType(ResourceLocation rl) {
        return DimensionManager.getRegistry().getOrDefault(rl);
    }

    private static ServerWorld getWorld(MinecraftServer server, DimensionType type, boolean force) {
        return DimensionManager.getWorld(server, type, force, force);
    }

    private static boolean containsRegistry(ResourceLocation rl) {
        return DimensionManager.getRegistry().getOrDefault(rl) != null;
    }

    private static void unregister(ResourceLocation rl, DimensionType removeType) {
        // unregister the id
        try {
            // data might not be set
            DimensionManager.unregisterDimension(removeType.getId() + 1);
        } catch(Exception ex) {
        }
        // remove entry in "savedEntries"
        ReflectionUtils.removeDimensionSaveEntry(rl);
        // remove the registry
        ClearableRegistry<DimensionType> reg = (ClearableRegistry<DimensionType>) DimensionManager.getRegistry();
        ArrayList<ResourceLocation> regs = new ArrayList<>();
        ArrayList<DimensionType> types = new ArrayList<>();
        for(DimensionType type : reg) {
            if(type == removeType) {
                continue;
            }
            types.add(type);
            regs.add(reg.getKey(type));
        }
        reg.clear();
        for(int i = 0; i < regs.size(); i++) {
            DimensionType type = types.get(i);
            reg.register(type.getId() + 1, regs.get(i), type);
        }
    }

    // -------------------------------------------------------------------------
    // normal stuff
    // -------------------------------------------------------------------------
    public static String getName(IWorld ws) {
        if(ws == null) {
            return "null";
        }
        DimensionType type = ws.getDimension().getType();
        ResourceLocation rl = getRegistry(type);
        return rl == null ? "null" : rl.getPath();
    }

    public static ServerWorld get(MinecraftServer server, String name) {
        String domain;
        if(name.equals("overworld") || name.equals("the_nether") || name.equals("the_end")) {
            domain = "minecraft";
        } else {
            domain = KajetansMod.MODID;
        }
        ResourceLocation rl = new ResourceLocation(domain, name);
        DimensionType type = getDimensionType(rl);
        if(type == null) {
            return null;
        }
        return getWorld(server, type, true);
    }

    public static boolean register(String name) {
        ResourceLocation rl = new ResourceLocation(KajetansMod.MODID, name);
        if(containsRegistry(rl)) {
            return false;
        }
        DimensionType dt = DimensionManager.registerDimension(rl, MOD_DIMENSION, null, true);
        DimensionManager.keepLoaded(dt, true);
        return true;
    }

    public static boolean unregister(MinecraftServer server, String name) {
        ResourceLocation rl = new ResourceLocation(KajetansMod.MODID, name);
        DimensionType removeType = getDimensionType(rl);
        if(removeType == null) {
            return false;
        }
        ServerWorld ws = getWorld(server, removeType, true);
        if(ws != null) {
            return false;
        }
        unregister(rl, removeType);
        return true;
    }
}
