package common.init;

import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import common.biome.Biome;
import common.block.foliage.LeavesType;
import common.collect.Lists;
import common.collect.Maps;
import common.collect.Sets;
import common.dimension.Area;
import common.dimension.CloudType;
import common.dimension.DimType;
import common.dimension.Dimension;
import common.dimension.Domain;
import common.dimension.Galaxy;
import common.dimension.Moon;
import common.dimension.Planet;
import common.dimension.Sector;
import common.dimension.Semi;
import common.dimension.Space;
import common.dimension.Star;
import common.dimension.Dimension.GeneratorType;
import common.dimension.Dimension.ReplacerType;
import common.log.Log;
import common.rng.Random;
import common.tags.TagObject;
import common.util.PortalType;
import common.world.State;
import common.world.Weather;

import java.util.Set;

public abstract class UniverseRegistry {
	public static final int MORE_DIM_ID = 1000;
	public static final long EARTH_YEAR = 8766144L;
	
	private static final List<Dimension> BASE_DIMS = Lists.newArrayList();
	private static final Map<Integer, Dimension> BASE_REGISTRY = Maps.newHashMap();
	private static final Map<String, Dimension> BASE_ALIASES = Maps.newHashMap();
	private static final Map<String, String> BASE_MAP = Maps.newHashMap();
	private static final Map<String, String> BASE_NAMES = Maps.newHashMap();
	private static final Map<Integer, Integer> PORTALS = Maps.newHashMap();
	
	private static final List<Dimension> DIMENSIONS = Lists.newArrayList();
	private static final Map<Integer, Dimension> REGISTRY = Maps.newTreeMap();
	private static final Map<String, Dimension> ALIASES = Maps.newTreeMap();
	private static final Set<String> NAMES = Sets.newTreeSet();
	
//	private static final Map<String, Moon> MOONS = Maps.newHashMap();
//	private static final Map<String, Planet> PLANETS = Maps.newHashMap();
//	private static final Map<String, Star> STARS = Maps.newHashMap();
	private static final Map<String, Sector> SECTORS = Maps.newHashMap();
	private static final Map<String, Galaxy> GALAXIES = Maps.newHashMap();
	private static final Map<String, Domain> DOMAINS = Maps.newHashMap();
	
	private static final Map<Moon, Planet> MOON_MAP = Maps.newHashMap();
	private static final Map<Planet, Star> PLANET_MAP = Maps.newHashMap();
	private static final Map<Star, Sector> STAR_MAP = Maps.newHashMap();
	private static final Map<Sector, Galaxy> SECTOR_MAP = Maps.newHashMap();
	private static final Map<Area, Domain> AREA_MAP = Maps.newHashMap();
	
	private static int nextDimId;
	
	public static void clear() {
		nextDimId = UniverseRegistry.MORE_DIM_ID;
		ALIASES.clear();
		NAMES.clear();
		REGISTRY.clear();
		DIMENSIONS.clear();
		SECTORS.clear();
		GALAXIES.clear();
		DOMAINS.clear();
		MOON_MAP.clear();
		PLANET_MAP.clear();
		STAR_MAP.clear();
		SECTOR_MAP.clear();
		AREA_MAP.clear();
		register(Space.INSTANCE);
		for(Dimension dim : BASE_REGISTRY.values()) {
			register(dim.copy());
		}
		for(Entry<String, String> entry : BASE_MAP.entrySet()) {
			assign(entry.getKey(), entry.getValue());
		}
	}
	
	public static void fromTags(TagObject tag) {
		List<TagObject> list = tag.getList("Dimensions");
		for(int z = 0; z < list.size(); z++) {
			Dimension dim = Dimension.getByTag(list.get(z));
			if(!REGISTRY.containsKey(dim.getDimensionId()) && !ALIASES.containsKey(dim.getDimensionName()))
				register(dim);
		}
		
		list = tag.getList("Names");
		for(int z = 0; z < list.size(); z++) {
			TagObject data = list.get(z);
			String id = data.getString("ID");
//			if(BASE_ALIASES.containsKey(id)) {
			Dimension dim = ALIASES.get(id);
			if(dim != null && dim != Space.INSTANCE)
				dim.readTags(data);
//			}
		}
		
		list = tag.getList("Sectors");
		for(int z = 0; z < list.size(); z++) {
			TagObject data = list.get(z);
			String id = data.getString("ID");
			Sector sector = SECTORS.get(id);
			if(sector == null)
				SECTORS.put(id, sector = new Sector(id));
			sector.readTags(data);
		}
		
		list = tag.getList("Galaxies");
		for(int z = 0; z < list.size(); z++) {
			TagObject data = list.get(z);
			String id = data.getString("ID");
			Galaxy galaxy = GALAXIES.get(id);
			if(galaxy == null)
				GALAXIES.put(id, galaxy = new Galaxy(id));
			galaxy.readTags(data);
		}
		
		list = tag.getList("Domains");
		for(int z = 0; z < list.size(); z++) {
			TagObject data = list.get(z);
			String id = data.getString("ID");
			Domain domain = DOMAINS.get(id);
			if(domain == null)
				DOMAINS.put(id, domain = new Domain(id));
			domain.readTags(data);
		}
		
		list = tag.getList("Barycenters");
		for(int z = 0; z < list.size(); z++) {
			TagObject link = list.get(z);
			if(!assign(link.getString("Celestial"), link.getString("Center")))
				Log.TICK.warn("Konnte '" + link.getString("Celestial") + "' nicht zu '" + link.getString("Center") + "' zuweisen");
		}
	}
	
	public static TagObject toTags() {
		TagObject tag = new TagObject();
		
		List<TagObject> list = Lists.newArrayList();
		for(Dimension dim : DIMENSIONS) {
			if(!BASE_REGISTRY.containsKey(dim.getDimensionId()) && dim != Space.INSTANCE)
				list.add(dim.toTags());
		}
		if(!list.isEmpty())
			tag.setList("Dimensions", list);
		
		list = Lists.newArrayList();
		for(Dimension dim : DIMENSIONS) {
			if(/* BASE_REGISTRY.containsKey(dim.getDimensionId()) */ dim != Space.INSTANCE) {
				TagObject data = new TagObject();
				dim.writeTags(data);
				if(!data.isEmpty()) {
					data.setString("ID", dim.getDimensionName());
					list.add(data);
				}
			}
		}
		if(!list.isEmpty())
			tag.setList("Names", list);
		
		list = Lists.newArrayList();
		for(Sector sector : SECTORS.values()) {
			TagObject data = new TagObject();
			sector.writeTags(data);
			if(!data.isEmpty()) {
				data.setString("ID", sector.id);
				list.add(data);
			}
		}
		if(!list.isEmpty())
			tag.setList("Sectors", list);
		
		list = Lists.newArrayList();
		for(Galaxy galaxy : GALAXIES.values()) {
			TagObject data = new TagObject();
			galaxy.writeTags(data);
			if(!data.isEmpty()) {
				data.setString("ID", galaxy.id);
				list.add(data);
			}
		}
		if(!list.isEmpty())
			tag.setList("Galaxies", list);
		
		list = Lists.newArrayList();
		for(Domain domain : DOMAINS.values()) {
			TagObject data = new TagObject();
			domain.writeTags(data);
			if(!data.isEmpty()) {
				data.setString("ID", domain.id);
				list.add(data);
			}
		}
		if(!list.isEmpty())
			tag.setList("Domains", list);
		
		list = Lists.newArrayList();
		for(Entry<Moon, Planet> entry : MOON_MAP.entrySet()) {
			if(BASE_REGISTRY.containsKey(entry.getKey().getDimensionId()))
				continue;
			TagObject link = new TagObject();
			link.setString("Celestial", entry.getKey().getDimensionName());
			link.setString("Center", entry.getValue().getDimensionName());
			list.add(link);
		}
		for(Entry<Planet, Star> entry : PLANET_MAP.entrySet()) {
			if(BASE_REGISTRY.containsKey(entry.getKey().getDimensionId()))
				continue;
			TagObject link = new TagObject();
			link.setString("Celestial", entry.getKey().getDimensionName());
			link.setString("Center", entry.getValue().getDimensionName());
			list.add(link);
		}
		for(Entry<Star, Sector> entry : STAR_MAP.entrySet()) {
			if(BASE_REGISTRY.containsKey(entry.getKey().getDimensionId()))
				continue;
			TagObject link = new TagObject();
			link.setString("Celestial", entry.getKey().getDimensionName());
			link.setString("Center", entry.getValue().id);
			list.add(link);
		}
		for(Entry<Sector, Galaxy> entry : SECTOR_MAP.entrySet()) {
			if(BASE_MAP.containsKey(entry.getKey().id))
				continue;
			TagObject link = new TagObject();
			link.setString("Celestial", entry.getKey().id);
			link.setString("Center", entry.getValue().id);
			list.add(link);
		}
		for(Entry<Area, Domain> entry : AREA_MAP.entrySet()) {
			if(BASE_REGISTRY.containsKey(entry.getKey().getDimensionId()))
				continue;
			TagObject link = new TagObject();
			link.setString("Celestial", entry.getKey().getDimensionName());
			link.setString("Center", entry.getValue().id);
			list.add(link);
		}
		if(!list.isEmpty())
			tag.setList("Barycenters", list);
		
		return tag;
	}
	
	public static Planet registerPlanet(String star, String name, String custom, int sky, int fog, int clouds, long orbit, long rotation, 
			float offset, float gravity, float temperature, int brightness) {
		if(!ALIASES.containsKey(star) || ALIASES.get(star).getType() != DimType.STAR || ALIASES.containsKey(name))
			return null;
		Planet dim = new Planet(nextDimId++, name, sky, fog, clouds, orbit, rotation, offset, gravity, temperature, brightness);
		register(dim);
		assign(name, star);
		dim.setTimeQualifier(3);
		dim.setCustomName(custom);
		return dim;
	}
	
	public static Dimension[] registerPreset(Dimension preset) {
		if(ALIASES.containsKey(preset.getDimensionName()))
			return new Dimension[] {preset};
		Random rand = new Random();
		String pname = NameRegistry.FANTASY.generate(rand, rand.range(2, 5));
		preset = preset.copy(nextDimId++, pname.toLowerCase());
		preset.setCustomName(pname);
		register(preset);
		if(preset.getType() == DimType.PLANET) {
			String galaxy = NameRegistry.FANTASY.generate(rand, rand.range(2, 5));
			String sector = NameRegistry.FANTASY.generate(rand, rand.range(2, 5));
			String sname = NameRegistry.FANTASY.generate(rand, rand.range(2, 5));
			Star star = new Star(nextDimId++, sname.toLowerCase(), 0xff0000 | (rand.range(0x60, 0xa0) << 8), 
					rand.frange(200.0f, 400.0f), rand.frange(5000.0f, 7000.0f), 
					rand.pick(Blocks.lava.getState(), Blocks.magma.getState()), rand.range(64, 212));
			star.setCustomName(sname);
			register(star);
			assign(preset.getDimensionName(), star.getDimensionName());
			assign(star.getDimensionName(), sector.toLowerCase());
			SECTORS.get(sector.toLowerCase()).setCustomName(sector);
			assign(sector.toLowerCase(), galaxy.toLowerCase());
			GALAXIES.get(galaxy.toLowerCase()).setCustomName(galaxy);
			return new Dimension[] {preset, star};
		}
		else if(preset.getType() == DimType.AREA) {
			String domain = NameRegistry.FANTASY.generate(rand, rand.range(2, 5));
			assign(preset.getDimensionName(), domain.toLowerCase());
			DOMAINS.get(domain.toLowerCase()).setCustomName(domain);
		}
		return new Dimension[] {preset};
	}
	
	public static boolean assign(String body, String center) {
		Dimension celestial = ALIASES.get(body);
		Dimension barycenter = ALIASES.get(center);
		if(celestial != null && celestial.getType() == DimType.MOON && barycenter != null 
				&& barycenter.getType() == DimType.PLANET) {
			MOON_MAP.put((Moon)celestial, (Planet)barycenter);
			((Planet)barycenter).addMoon((Moon)celestial);
			return true;
		}
		else if(celestial != null && celestial.getType() == DimType.PLANET && barycenter != null 
				&& barycenter.getType() == DimType.STAR) {
			PLANET_MAP.put((Planet)celestial, (Star)barycenter);
			((Star)barycenter).addPlanet((Planet)celestial);
			return true;
		}
		else if(celestial != null && celestial.getType() == DimType.STAR && barycenter == null) {
			Sector sector = SECTORS.get(center);
			if(sector == null) {
				SECTORS.put(center, sector = new Sector(center));
				if(BASE_NAMES.containsKey(center))
					sector.setCustomName(BASE_NAMES.get(center));
			}
			STAR_MAP.put((Star)celestial, sector);
			sector.addStar((Star)celestial);
			return true;
		}
		else if(celestial != null && celestial.getType() == DimType.AREA && barycenter == null) {
			Domain domain = DOMAINS.get(center);
			if(domain == null) {
				DOMAINS.put(center, domain = new Domain(center));
				if(BASE_NAMES.containsKey(center))
					domain.setCustomName(BASE_NAMES.get(center));
			}
			AREA_MAP.put((Area)celestial, domain);
			domain.addArea((Area)celestial);
			return true;
		}
		else if(celestial == null && barycenter == null) {
			Sector sector = SECTORS.get(body);
			if(sector == null) {
				SECTORS.put(body, sector = new Sector(body));
				if(BASE_NAMES.containsKey(body))
					sector.setCustomName(BASE_NAMES.get(body));
			}
			Galaxy galaxy = GALAXIES.get(center);
			if(galaxy == null) {
				GALAXIES.put(center, galaxy = new Galaxy(center));
				if(BASE_NAMES.containsKey(center))
					galaxy.setCustomName(BASE_NAMES.get(center));
			}
			SECTOR_MAP.put(sector, galaxy);
			galaxy.addSector(sector);
			return true;
		}
		else {
			return false;
		}
	}
	
	private static void register(Dimension dim) {
		DIMENSIONS.add(dim);
		ALIASES.put(dim.getDimensionName(), dim);
		NAMES.add(dim.getDimensionName());
		REGISTRY.put(dim.getDimensionId(), dim);
	}
	
	public static List<Dimension> getDimensions() {
		return DIMENSIONS;
	}
	
	public static Dimension getDimension(int dim) {
		return REGISTRY.get(dim);
	}
	
	public static Dimension getDimension(String name) {
		return ALIASES.get(name);
	}

	public static Set<String> getWorldNames() {
		return NAMES;
	}

	public static String getDefaultName(String name) {
		return BASE_NAMES.get(name);
	}
	
	public static List<Dimension> getBaseDimensions() {
		return BASE_DIMS;
	}
	
	public static int getPortalDest(int src, PortalType portal) {
		return PORTALS.containsKey((portal.ordinal() << 20) | src) ? PORTALS.get((portal.ordinal() << 20) | src) : 
				(PORTALS.containsKey(portal.ordinal() | 0x7ff00000) ? PORTALS.get(portal.ordinal() | 0x7ff00000) : src);
	}
	
//    public static Text getUnformattedName(Dimension dim, boolean full) {
//    	Text base = dim.getNameComponent();
////    	if(dim.getCustomName() != null && !dim.getCustomName().isEmpty())
////    		base = new TextComponent(dim.getCustomName());
////    	else if(dim.getDimensionId() >= Constants.MORE_DIM_ID)
//////    		base = new Translation("dimension." + dim.getType().getName(), dim.getDimensionName());
////    		base = new Translation("preset." + dim.getDimensionName());
////    	else
////    		base = new Translation("dimension." + dim.getDimensionName());
//    	if(!full)
//    		return base;
//    	switch(dim.getType()) {
//	    	case MOON:
//	    		dim = MOON_MAP.get(dim);
//	    		if(dim == null)
//	    			return base;
//	    		base.appendText(" / ").appendSibling(dim.getNameComponent());
//	    	case PLANET:
//	    		dim = PLANET_MAP.get(dim);
//	    		if(dim == null)
//	    			return base;
//	    		base.appendText(" / ").appendSibling(dim.getNameComponent());
//	    	case STAR:
//	    		Sector sector = STAR_MAP.get(dim);
//	    		if(sector == null)
//	    			return base;
//	    		base.appendText(" / ").appendSibling(sector.getNameComponent());
//	    		Galaxy galaxy = SECTOR_MAP.get(sector);
//	    		if(galaxy == null)
//	    			return base;
//	    		base.appendText(" / ").appendSibling(galaxy.getNameComponent());
//	    		break;
//	    	case AREA:
//	    		Domain domain = AREA_MAP.get(dim);
//	    		if(domain == null)
//	    			return base;
//	    		base.appendText(" / ").appendSibling(domain.getNameComponent());
//	    		break;
//	    	default:
//	    		break;
//    	}
//    	return base;
//    }
	
    public static String getFormattedName(Dimension dim, boolean full) {
    	String base = dim.getNameString();
//    	if(dim.getCustomName() != null && !dim.getCustomName().isEmpty())
//    		base = dim.getCustomName();
//    	else if(dim.getDimensionId() >= Constants.MORE_DIM_ID)
////    		base = I18n.format("dimension." + dim.getType().getName(), dim.getDimensionName());
//			base = I18n.format("preset." + dim.getDimensionName());
//    	else
//    		base = I18n.format("dimension." + dim.getDimensionName());
    	if(!full)
    		return base;
    	switch(dim.getType()) {
	    	case MOON:
	    		dim = MOON_MAP.get(dim);
	    		if(dim == null)
	    			return base;
	    		base += " / " + dim.getNameString();
	    	case PLANET:
	    		dim = PLANET_MAP.get(dim);
	    		if(dim == null)
	    			return base;
	    		base += " / " + dim.getNameString();
	    	case STAR:
	    		Sector sector = STAR_MAP.get(dim);
	    		if(sector == null)
	    			return base;
	    		base += " / " + sector.getNameString();
	    		Galaxy galaxy = SECTOR_MAP.get(sector);
	    		if(galaxy == null)
	    			return base;
	    		base += " / " + galaxy.getNameString();
	    		break;
	    	case AREA:
	    		Domain domain = AREA_MAP.get(dim);
	    		if(domain == null)
	    			return base;
	    		base += " / " + domain.getNameString();
	    		break;
	    	default:
	    		break;
    	}
    	return base;
    }
	
	private static void registerDimension(String name, Dimension dim) {
		dim.setCustomName(name);
		BASE_NAMES.put(dim.getDimensionName(), name);
		if(dim.getType() == DimType.PLANET || dim.getType() == DimType.AREA || dim.getType() == DimType.SEMI)
			BASE_DIMS.add(dim);
		BASE_REGISTRY.put(dim.getDimensionId(), dim);
		BASE_ALIASES.put(dim.getDimensionName(), dim);
	}
	
	private static void registerGalaxy(String name, String galaxy) {
		BASE_NAMES.put(galaxy, name);
	}
	
	private static void registerSector(String name, String sector, String galaxy) {
		BASE_MAP.put(sector, galaxy);
		BASE_NAMES.put(sector, name);
	}
	
	private static void registerDomain(String name, String domain) {
		BASE_NAMES.put(domain, name);
	}
	
	private static void registerDimension(String name, Dimension dim, String base) {
		registerDimension(name, dim);
		BASE_MAP.put(dim.getDimensionName(), base);
	}
	
	private static void registerPortal(PortalType portal, String src, String dest) {
		PORTALS.put((portal.ordinal() << 20) | BASE_ALIASES.get(src).getDimensionId(), BASE_ALIASES.get(dest).getDimensionId());
	}
	
	private static void registerPortal(PortalType portal, String dest) {
		PORTALS.put(portal.ordinal() | 0x7ff00000, BASE_ALIASES.get(dest).getDimensionId());
	}

	public static void register() {
		registerGalaxy("Milchstraße", "milkyway");
		registerSector("Solar", "solar", "milkyway");
		registerDimension("Sol", new Star(2, "sol", 0xff7f00, 274.0f, 5778.0f, Blocks.lava.getState(), 128).setTimeQualifier(1), "solar");
		registerDimension("Terra", new Planet(1, "terra", 0xffffffff, 0xc0d8ff, 0xffffff, UniverseRegistry.EARTH_YEAR, 24000L, 28.0f, 9.81f, 
				259.15f).setTimeQualifier(0)
				.setPerlinGen(Blocks.stone.getState(), Blocks.water.getState(), 63)
				.setBiomeReplacer(Blocks.gravel.getState())
				.setBiomeGen(Biome.FOREST, false, 4, 4, 6, 50, 50, Biome.MUSHROOMPLAINS).enableMobs().enableSnow()
				.setFrostBiomes(Biome.ICEPLAINS, Biome.ICEPLAINS, Biome.ICEPLAINS, Biome.COLDTAIGA, Biome.MEGATAIGA)
				.setColdBiomes(Biome.FOREST, Biome.EXTREMEHILLS, Biome.TAIGA, Biome.PLAINS)
				.setMediumBiomes(Biome.FOREST, Biome.ROOFEDFOREST, Biome.EXTREMEHILLS, Biome.PLAINS, Biome.BIRCHFOREST, 
						Biome.SWAMPLAND, Biome.JUNGLE)
				.setHotBiomes(Biome.DESERT, Biome.DESERT, Biome.DESERT, Biome.SAVANNA, Biome.SAVANNA, Biome.PLAINS)
				.enableCavesRavines(Blocks.lava.getState()).setDungeons(8)
				.addLake(Blocks.water.getState(), null, Blocks.grass.getState(), 4, 0, 255, false)
				.addLake(Blocks.lava.getState(), Blocks.stone.getState(), null, 8, 8, 255, true)
				.addLiquid(Blocks.flowing_water.getState(), 50, 8, 255, false)
				.addLiquid(Blocks.flowing_lava.getState(), 20, 8, 255, true)
				.addMetalOres(MetalType.values())
				.addOre(Blocks.dirt.getState(), 10, 0, 33, 0, 256, false)
				.addOre(Blocks.gravel.getState(), 8, 0, 33, 0, 256, false)
				.addOre(Blocks.rock.getState(), 6, 0, 22, 24, 72, false)
				.addOre(Blocks.coal_ore.getState(), 20, 0, 17, 0, 128, false)
				.addOre(Blocks.redstone_ore.getState(), 8, 0, 8, 0, 16, false)
				.addOre(Blocks.lapis_ore.getState(), 1, 0, 7, 16, 16, true)
				.addOre(Blocks.diamond_ore.getState(), 1, 0, 8, 0, 16, false)
				.addOre(Blocks.ruby_ore.getState(), 1, 0, 4, 12, 8, true)
				.addOre(Blocks.cinnabar_ore.getState(), 1, 0, 11, 0, 24, false)
				.enableVillages().enableMineshafts().enableScattered().enableStrongholds(), "sol");
		registerDimension("Luna", new Moon(3, "luna", 0x333333, 0x333333, 655728L, 655728L, 1.62f, 210.0f, 8)
				.setPerlinGen(Blocks.moon_rock.getState(), Blocks.air.getState(), 63).setBiome(Biome.MOON)
				.setTimeQualifier(1), "terra");

		registerDimension("Merkur", new Planet(4, "mercury", 0x666666, 0x535353, 0x858585, 2111297L, 1407509L, 3.7f, 440.0f)
				.setPerlinGen(Blocks.moon_rock.getState(), Blocks.air.getState(), 63)
				.setTimeQualifier(1), "sol");
		registerDimension("Venus", new Planet(5, "venus", 0xc0c0c0, 0xa0a0a0, 0xe0e0e0, 5392908L, 5832449L, 8.87f, 737.0f)
				.setPerlinGen(Blocks.sand.getState(), Blocks.air.getState(), 63)
				.setTimeQualifier(1), "sol");
		registerDimension("Mars", new Planet(6, "mars", 0xd6905b, 0xbd723a, 0xbd9273, 16487781L, 24623L, 3.71f, 208.0f)
				.setPerlinGen(Blocks.red_sand.getState(), 
				Blocks.air.getState(), 63).setTimeQualifier(1), "sol");
		registerDimension("Jupiter", new Planet(7, "jupiter", 0xffd5ba, 0xb89f90, 0xc7b5a9, 103989391L, 9925L, 24.79f, 163.0f).enableDenseFog()
				.setFlatGen(Blocks.hydrogen.getState(), 256).setTimeQualifier(1).setCloudHeight(576.0f), "sol");
		registerDimension("Saturn", new Planet(8, "saturn", 0xf1d1a1, 0xd3b385, 0xeed7b5, 258141008L, 10656L, 10.44f, 133.0f).enableDenseFog()
				.setFlatGen(Blocks.hydrogen.getState(), 256).setTimeQualifier(1).setCloudHeight(576.0f), "sol");
		registerDimension("Uranus", new Planet(9, "uranus", 0xcee6ff, 0xadd2f9, 0x8eb0d3, 736503770L, 17240L, 8.87f, 78.0f)
				.setPerlinGen(Blocks.packed_ice.getState(), Blocks.water.getState(), 70)
				.addOre(Blocks.diamond_ore.getState(), 4, 4, 12, 0, 60, false)
				.setTimeQualifier(1), "sol");
		registerDimension("Neptun", new Planet(10, "neptune", 0xb4d9ff, 0x85bef9, 0x649bd3, 1444584441L, 16110L, 11.15f, 72.0f)
				.setPerlinGen(Blocks.packed_ice.getState(), Blocks.water.getState(), 70)
				.addOre(Blocks.diamond_ore.getState(), 4, 2, 1, 0, 60, false)
				.setTimeQualifier(1), "sol");
		registerDimension("Ceres", new Planet(11, "ceres", 0x666666, 0x535353, 0x858585, 40315496L, 9074L, 0.27f, 167.0f)
				.setPerlinGen(Blocks.moon_rock.getState(), Blocks.air.getState(), 63)
				.setTimeQualifier(1), "sol");
		registerDimension("Pluto", new Planet(12, "pluto", 0x666666, 0x535353, 0x858585, 2173127098L, 153293L, 0.62f, 40.0f)
				.setPerlinGen(Blocks.moon_rock.getState(), Blocks.air.getState(), 63)
				.setTimeQualifier(1), "sol");
		registerDimension("Haumea", new Planet(13, "haumea", 0x666666, 0x535353, 0x858585, 2487831667L, 3914L, 0.63f, 48.0f)
				.setPerlinGen(Blocks.moon_rock.getState(), Blocks.air.getState(), 63)
				.setTimeQualifier(1), "sol");
		registerDimension("Makemake", new Planet(14, "makemake", 0x666666, 0x535353, 0x858585, 2684193293L, 22826L, 0.4f, 30.0f)
				.setPerlinGen(Blocks.moon_rock.getState(), Blocks.air.getState(), 63)
				.setTimeQualifier(1), "sol");
		registerDimension("Eris", new Planet(15, "eris", 0x666666, 0x535353, 0x858585, 4900274496L, 378862L, 0.82f, 30.0f)
				.setPerlinGen(Blocks.moon_rock.getState(), Blocks.air.getState(), 63)
				.setTimeQualifier(1), "sol");
		
		registerDimension("Gi'rok", new Star(100, "girok", 0xff8f00, 232.0f, 5220.0f, Blocks.lava.getState(), 112).setTimeQualifier(2), "solar");
		registerDimension("'Elbenplanet Gharoth'", new Planet(101, "gharoth", 0xffffffff, 0xc0d8ff, 0xffffff, 4837386L, 52960L, 30.0f, 10.0f, 257.3f)
				.setTimeQualifier(2).setSimpleGen(Blocks.dirt.getState(), Blocks.water.getState(), 64)
				.setSimpleReplacer(Blocks.gravel.getState(), Blocks.sand.getState()).setBiome(Biome.ELVENFOREST)
				.enableCaves(Blocks.air.getState()).setDungeons(4).enableMobs().enableSnow()
				.addLake(Blocks.water.getState(), null, Blocks.grass.getState(), 4, 0, 255, false)
				.addLake(Blocks.lava.getState(), null, null, 8, 8, 255, true)
				.addLiquid(Blocks.flowing_water.getState(), 50, 8, 255, false)
				.addLiquid(Blocks.flowing_lava.getState(), 20, 8, 255, true)
				.addOre(Blocks.thetium_ore.getState(), 1, 0, 3, 0, 14, false)
				.addOre(Blocks.gyriyn_ore.getState(), 0, 2, 3, 0, 12, false), "girok");
		registerDimension("'Vampirplanet Transsylvanien'", new Planet(102, "transylvania", 0xffffffff, 0xc0d8ff, 0xffffff, 33850466L, 49760L, 20.0f, 10.0f, 255.5f)
				.setTimeQualifier(5).setPerlinGen(Blocks.rock.getState(), Blocks.water.getState(), 63)
				.setBiomeReplacer(Blocks.gravel.getState()).setBiomeGen(Biome.FOREST, true, 5, 3, 3, 30)
				.enableCavesRavines(Blocks.lava.getState()).setDungeons(10).enableMobs().enableSnow()
				.addLake(Blocks.water.getState(), null, Blocks.grass.getState(), 4, 0, 255, false)
				.addLake(Blocks.lava.getState(), null, null, 8, 8, 255, true)
				.addLiquid(Blocks.flowing_water.getState(), 50, 8, 255, false)
				.addLiquid(Blocks.flowing_lava.getState(), 20, 8, 255, true)
				.addOre(Blocks.coal_ore.getState(), 12, 0, 14, 4, 28, false)
				.addOre(Blocks.lead_ore.getState(), 2, 0, 8, 0, 8, false)
				.addOre(Blocks.ardite_ore.getState(), 0, 2, 3, 0, 12, false)
				.addOre(Blocks.nichun_ore.getState(), 0, 10, 1, 0, 10, false), "girok");
		registerDimension("'Eismond Yrdinath'", new Moon(103, "yrdinath", 0xccccff, 0xccccff, 46743637L, 17460L, 2.5f, 239.15f, 8).setTimeQualifier(4)
				.setPerlinGen(Blocks.snow.getState(), Blocks.ice.getState(), 63).setBiome(Biome.SNOWLAND)
				.enableMobs().enableSnow().setWeather(Weather.SNOW), "transylvania");
		registerDimension("'Wüstenplanet Me'sar'", new Planet(104, "mesar", 0xff7f3f, 0xff6022, 0xff6f00, 56643366L, 87340L, 11.0f, 333.15f)
				.setTimeQualifier(5).setPerlinGen(Blocks.rock.getState(), Blocks.air.getState(), 63)
				.setBiomeReplacer(Blocks.red_sand.getState())
				.setBiomeGen(Biome.MESA, true, 3, 1000, 100000, 100000)
				.enableCavesRavines(Blocks.lava.getState()).enableMobs()
				.addLake(Blocks.lava.getState(), null, null, 8, 8, 255, true)
				.addLiquid(Blocks.flowing_lava.getState(), 20, 8, 255, true)
				.addOre(Blocks.iron_ore.getState(), 6, 2, 24, 0, 64, false)
				.addOre(Blocks.gold_ore.getState(), 4, 2, 20, 0, 48, false)
				.addOre(Blocks.lead_ore.getState(), 6, 0, 14, 0, 32, false)
				.addOre(Blocks.copper_ore.getState(), 8, 2, 12, 0, 52, false)
				.addOre(Blocks.coal_ore.getState(), 8, 4, 30, 0, 16, false)
				.addOre(Blocks.stone.getState(), 8, 4, 33, 0, 80, false), "girok");

		registerGalaxy("Drkthrn", "drkthrn");
		registerSector("Blvck", "blvck", "drkthrn");
		registerDimension("Ov'rol", new Star(120, "ovrol", 0x000000, 302.0f, 12666.0f, Blocks.goo.getState(), 192), "blvck");
		registerDimension("'Schwarzplanet'", new Planet(121, "blackplanet", 0x000000, 0x000000, 0x000000, 4632918508L, 204556L, 12.0f, 0.0f)
				.setPerlinGen(Blocks.blackened_stone.getState(), Blocks.goo.getState(), 63)
				.setBiomeReplacer(Blocks.blackened_cobble.getState()).setBiome(Biome.BLACKENED)
				.enableCaves(Blocks.air.getState()).setDungeons(4).enableMobs()
				.addLake(Blocks.goo.getState(), null, null, 8, 8, 255, true)
//				.addOre(Blocks.PLACEHOLDER_ore.getState(), 0, 2, 3, 0, 12, false)
				, "ovrol");
		
		registerDimension("Der Warp", new Semi(-1, "warp", 0x0c001f, 0x0c001f, 0x190033, 285.0f, 3).setCloudTexture(CloudType.DENSE).setCloudHeight(238.0f)
				.setPerlinGen(Blocks.obsidian.getState(), Blocks.lava.getState(), 63)
				.setBiome(Biome.CHAOS).enableCavesRavines(Blocks.air.getState()).enableLongCaves().enableMobs().enableSnow()
				.addLake(Blocks.water.getState(), null, Blocks.obsidian.getState(), 8, 0, 255, false)
				.addLake(Blocks.lava.getState(), null, null, 1, 8, 255, false)
				.addLiquid(Blocks.flowing_water.getState(), 1, 8, 255, false)
				.addLiquid(Blocks.flowing_lava.getState(), 40, 8, 255, true)
				.setStarBrightness(0.9f).setDeepStarBrightness(0.6f)
				.setStarColorSin(25.0f, 0.1f, 0.25f, 0xff00ff, 1, 4).setDeepStarColorSin(25.0f, 0.1f, 0.5f, 0xff00ff, 1, 4));

		registerDomain("Tian'Xin", "tianxin");
		registerDimension("Ni'enrath", new Area(-2, "nienrath", 0x7f00ff, 0x7f00ff, 276.15f, 1)
				.setPerlinGen(Blocks.tian.getState(), Blocks.springwater.getState(), 63).setBiome(Biome.TIAN)
				.setBiomeReplacer(Blocks.tian.getState()).enableLongCaves().enableMobs().enableSnow()
				.addLake(Blocks.springwater.getState(), Blocks.tian.getState(), Blocks.tian.getState(), 4, 0, 255, false)
				.addLiquid(Blocks.flowing_springwater.getState(), 50, 8, 255, false), "tianxin");
		
		registerDimension("Cyberspace", new Area(-3, "cyberspace", 0x000000, 0x000000, 293.15f, 15)
				.setFlatGen(Blocks.green_clay.getState(), 2)
				.enableMobs());

		registerDomain("Hölle", "hell");
		registerDimension("Kreis Thedric", new Area(-1001, "thedric", 0x330707, 0x330707, 347.15f, 2).enableLongCaves().enableMobs().enableFortresses()
				.enableWorldCeiling().enableDenseFog()
				.setCavernGen(Blocks.hellrock.getState(), Blocks.lava.getState(), 63)
				.setSurfaceReplacer(Blocks.gravel.getState(), Blocks.soul_sand.getState())
				.setBiome(Biome.UPPERHELL), "hell");
		registerDimension("Kreis Kyroth", new Area(-1002, "kyroth", 0x990000, 0x990000, 387.15f, 3).enableLongCaves().enableMobs()
				.setSimpleGen(Blocks.hellrock.getState(), Blocks.lava.getState(), 64)
				.setSimpleReplacer(Blocks.obsidian.getState(), Blocks.soul_sand.getState())
				.setBiome(Biome.LOWERHELL)
				.addLake(Blocks.lava.getState(), null, null, 4, 8, 255, false)
				.addLiquid(Blocks.flowing_lava.getState(), 40, 8, 255, true), "hell");
		registerDimension("Kreis Ahrd", new Area(-1003, "ahrd", 0xcc0000, 0xcc0000, 467.15f, 15).enableLongCaves().enableMobs()
				.setPerlinGen(Blocks.hellrock.getState(), Blocks.lava.getState(), 63)
				.setBiomeReplacer(Blocks.soul_sand.getState()).setBiome(Biome.HELLHILLS)
				.addLake(Blocks.lava.getState(), Blocks.soul_sand.getState(), Blocks.soul_sand.getState(), 
				2, 8, 255, false).addLiquid(Blocks.flowing_lava.getState(), 80, 8, 255, true), "hell");
		registerDimension("Kreis Mizorath", new Area(-1004, "mizorath", 0xff0000, 0xff0000, 1067.15f, 15).enableMobs()
				.setPerlinGen(Blocks.hellrock.getState(), Blocks.blood.getState(), 63)
				.setBiomeReplacer(Blocks.soul_sand.getState()).setBiome(Biome.SOULPLAINS), "hell");
		registerDimension("Kreis Dargoth", new Area(-1005, "dargoth", 0xff3f0c, 0xff3f0c, 1707.15f, 15).enableMobs()
				.setPerlinGen(Blocks.hellrock.getState(), Blocks.magma.getState(), 63)
				.setBiomeReplacer(Blocks.soul_sand.getState()).setBiome(Biome.SOULPLAINS), "hell");
		registerDimension("Kreis Aasirith", new Area(-1006, "aasirith", 0x191919, 0x191919, 2482.0f, 1).enableLongCaves().enableMobs()
				.setPerlinGen(Blocks.rock.getState(), Blocks.magma.getState(), 63)
				.setBiomeReplacer(Blocks.ash.getState()).setBiome(Biome.ASHLAND)
				.addLake(Blocks.lava.getState(), Blocks.rock.getState(), Blocks.rock.getState(), 
				2, 8, 255, false).addLiquid(Blocks.flowing_lava.getState(), 80, 8, 255, true), "hell");
		
		setPresets();
		clear();
	}

	private static Dimension addPreset(String name, String data) {
		return addPreset(name, "terra", data);
	}
	
	private static Dimension addPreset(String name, String base, String data) {
    	Dimension dim = BASE_ALIASES.get(base).copy(UniverseRegistry.MORE_DIM_ID, "preset");
    	TagObject ptag;
    	try {
			ptag = TagObject.parse("{" + data + "}");
		}
		catch(IllegalArgumentException e) {
			throw new RuntimeException(e);
		}
    	TagObject dtag = dim.toTags(true);
    	if(ptag.getBool("ClearGenerator")) {
    		ptag.remove("ClearGenerator");
    		dtag.remove("FloorBlock");
    		dtag.remove("CeilingBlock");
    		dtag.remove("Layers");
    		dtag.remove("AddBiomes");
    		dtag.remove("FrostBiomes");
    		dtag.remove("ColdBiomes");
    		dtag.remove("MediumBiomes");
    		dtag.remove("HotBiomes");
    		dtag.remove("Ores");
    		dtag.remove("Lakes");
    		dtag.remove("Liquids");
	    	dtag.setString("Generator", GeneratorType.FLAT.getName());
	    	dtag.setString("Replacer", ReplacerType.NONE.getName());
//	    	dtag.setBoolean("MobGen", false);
//	    	dtag.setBoolean("SnowGen", false);
	    	dtag.setBool("Caves", false);
	    	dtag.setBool("Ravines", false);
	    	dtag.setBool("AltCaves", false);
	    	dtag.setBool("Strongholds", false);
	    	dtag.setBool("Villages", false);
	    	dtag.setBool("Mineshafts", false);
	    	dtag.setBool("Scattered", false);
	    	dtag.setBool("Fortresses", false);
	    	dtag.setInt("Dungeons", 0);
	    	dtag.setInt("BiomeSize", 0);
	    	dtag.setInt("RiverSize", 4);
	    	dtag.setInt("SnowRarity", 6);
	    	dtag.setInt("SeaRarity", 50);
	    	dtag.setInt("AddRarity", 50);
	    	dtag.setInt("SeaLevel", 0);
			dtag.setString("DefaultBiome", Biome.NONE.name.toLowerCase());
			dtag.setBool("SemiFixed", false);
//			dtag.setString("DefaultWeather", Weather.CLEAR.getName());
			dtag.setString("DefaultLeaves", LeavesType.SPRING.getName());
			Dimension.writeState(dtag, "FillerBlock", Blocks.air.getState());
			Dimension.writeState(dtag, "TopBlock", Blocks.air.getState());
			Dimension.writeState(dtag, "SurfaceBlock", Blocks.air.getState());
			Dimension.writeState(dtag, "AltBlock1", Blocks.air.getState());
			Dimension.writeState(dtag, "AltBlock2", Blocks.air.getState());
			Dimension.writeState(dtag, "LiquidBlock", Blocks.air.getState());
    		Dimension.writeState(dtag, "CaveFillBlock", Blocks.air.getState());
    	}
    	dtag.merge(ptag);
    	dim.fromTags(dtag);
    	dim.setCustomName(name);
//		BASE_DIMS.add(dim);
		return dim;
    }
	
	private static Dimension addFlatPreset(String name, Biome biome, boolean populate, State main, Object ... layers) {
		return addFlatPreset(name, "terra", biome, populate, main, layers);
	}
	
	private static Dimension addFlatPreset(String name, String base, Biome biome, boolean populate, State main, Object ... layers) {
		Dimension dim = addPreset("Flach - " + name, base, "ClearGenerator:1b" + (populate ? "" : ",NoPopulation:1b"));
		dim.setBiome(biome);
		if(main != null)
			dim.setFlatGen(main, layers);
		return dim;
    }

    private static void setPresets()
    {
    	addPreset("Standard", "");
    	addPreset("Doppelte Höhe (128)", "BaseSize:17.0,Stretch:24.0,ScaleY:80.0,SeaLevel:127");
    	addPreset("Große Biome", "BiomeSize:6");
    	addPreset("Überdreht", "Amplification:2.0");
        addPreset("Wasserwelt", "ScaleX:5000.0,ScaleY:1000.0,ScaleZ:5000.0,Stretch:8.0,BDepthWeight:2.0,BDepthOffset:0.5,BScaleWeight:2.0,BScaleOffset:0.375,SeaLevel:511");
        addPreset("Inselland", "CoordScale:3000.0,HeightScale:6000.0,UpperLmtScale:250.0,Stretch:10.0");
        addPreset("Favorit des Gräbers", "ScaleX:5000.0,ScaleY:1000.0,ScaleZ:5000.0,Stretch:5.0,BDepthWeight:2.0,BDepthOffset:1.0,BScaleWeight:4.0,BScaleOffset:1.0");
        addPreset("Verrückte Berge", "CoordScale:738.41864,HeightScale:157.69133,UpperLmtScale:801.4267,LowerLmtScale:1254.1643,DepthScaleX:374.93652,DepthScaleZ:288.65228,"
        		+ "ScaleX:1355.9908,ScaleY:745.5343,ScaleZ:1183.464,BaseSize:1.8758626,Stretch:1.7137525,BDepthWeight:1.7553768,BDepthOffset:3.4701107,BScaleOffset:2.535211");
        addPreset("Trockenheit", "ScaleX:1000.0,ScaleY:3000.0,ScaleZ:1000.0,Stretch:10.0,SeaLevel:20");
        addPreset("Chaotische Höhlen", "UpperLmtScale:2.0,LowerLmtScale:64.0,SeaLevel:6");
        addPreset("Viel Glück", "LiquidBlock:lava,SeaLevel:40");
        
        addFlatPreset("Klassisch", Biome.PLAINS, false, Blocks.dirt.getState(), Blocks.bedrock.getState(), 2, Blocks.dirt.getState(),
        		Blocks.grass.getState()).enableVillages();
        
        addFlatPreset("Abbauwelt", Biome.EXTREMEHILLS, true, Blocks.stone.getState(), Blocks.bedrock.getState(), 230, Blocks.stone.getState(),
        		5, Blocks.dirt.getState(), Blocks.grass.getState()).enableStrongholds().enableMineshafts().setDungeons(8);
        
        addFlatPreset("Wasserwelt", Biome.SEA, false, Blocks.stone.getState(), Blocks.bedrock.getState(), 5, Blocks.stone.getState(),
        		52, Blocks.dirt.getState(), 5, Blocks.sand.getState(), 90, Blocks.water.getState());
        
        addFlatPreset("Oberfläche", Biome.PLAINS, true, Blocks.stone.getState(), Blocks.bedrock.getState(), 59, Blocks.stone.getState(),
        		3, Blocks.dirt.getState(), Blocks.grass.getState()).setBiomeReplacer(Blocks.gravel.getState()).enableVillages().enableStrongholds().enableMineshafts().setDungeons(8)
			.addLake(Blocks.water.getState(), null, Blocks.grass.getState(), 4, 0, 255, false).addLake(Blocks.lava.getState(), Blocks.stone.getState(), null, 8, 8, 255, true);
        
        addFlatPreset("Verschneites Königreich", Biome.ICEPLAINS, false, Blocks.stone.getState(), Blocks.bedrock.getState(), 59, Blocks.stone.getState(),
        		3, Blocks.dirt.getState(), Blocks.grass.getState(), Blocks.snow_layer.getState()).enableVillages();
        
        addFlatPreset("Verschneites Königreich +", Biome.ICEPLAINS, true, Blocks.stone.getState(), Blocks.bedrock.getState(), 59, Blocks.stone.getState(),
        		3, Blocks.dirt.getState(), Blocks.grass.getState(), Blocks.snow_layer.getState()).setBiomeReplacer(Blocks.gravel.getState()).enableVillages()
        		.addLake(Blocks.water.getState(), null, Blocks.grass.getState(), 4, 0, 255, false);
        
        addFlatPreset("Unendliche Grube", Biome.PLAINS, false, Blocks.dirt.getState(), 2, Blocks.cobblestone.getState(), 3, Blocks.dirt.getState(), Blocks.grass.getState())
        	.setBiomeReplacer(Blocks.gravel.getState()).enableVillages();
        
        addFlatPreset("Wüste", Biome.DESERT, false, Blocks.stone.getState(), Blocks.bedrock.getState(), 3, Blocks.stone.getState(), 52, Blocks.sandstone.getState())
        	.enableVillages().enableScattered();
        
        addFlatPreset("Redstonewelt", Biome.DESERT, false, Blocks.sandstone.getState(), Blocks.bedrock.getState(), 3, Blocks.stone.getState(),
        		52, Blocks.sandstone.getState());
        
        addPreset("Leer", "ClearGenerator:1b");
        addPreset("Alpha 1.2", "Strongholds:0b,Villages:0b,MineShafts:0b,Scattered:0b,Generator:simple,Replacer:simple,Ravines:0b,SeaLevel:64,AltBlock2:sand");
    }
}
