package common.world;

import java.util.Map;

import common.collect.Maps;
import common.rng.Random;
import common.rng.RngItem;
import common.rng.WeightedList;

public enum Weather {
	CLEAR("clear", "Schön", 0.0f, 0.0f, 12, 30, 9, 7), 
	FOG("fog", "Nebel", -0.2f, 0.8f, 15, 12, 20, 14), 
	COLD("cold", "Kalt", -0.4f, 0.1f, 20, 18, 25, 10), 
	HOT("hot", "Heiß", 0.1f, 0.0f, 0, 1, 0, 0), 
	FROST("frost", "Frost", -0.75f, 0.8f, 5, 4, 8, 4), 
	RAIN("rain", "Regen", false, -0.05f, 0.4f, 30, 45, 40, 25), 
	THUNDER("thunder", "Gewitter", true, -0.3f, 0.3f, 15, 25, 60, 8), 
	SNOW("snow", "Schnee", false, -0.85f, 0.3f, 10, 4, 14, 30), 
	HAIL("hail", "Hagel", false, -0.35f, 0.4f, 5, 8, 12, 3), 
	STORM("storm", "Sturm", false, true, -0.3f, 0.3f, 5, 10, 20, 15), 
	HAILSTORM("hailstorm", "Hagelsturm", true, -0.35f, 0.3f, 2, 1, 4, 2), 
	ICE("ice", "Eis", -0.85f, 0.15f, 10, 4, 16, 4), 
	SNOWSTORM("snowstorm", "Schneesturm", true, -0.85f, 0.25f, 2, 0, 2, 5), 
	CHILLED("chilled", "Permafrost", -8.0f, 0.0f), 
	ICEAGE("iceage", "Eiszeit", false, -8.0f, 0.45f), 
	FIRE("fire", "Feuer", 8.0f, 0.0f), 
	INFERNO("inferno", "Inferno", true, 8.0f, 0.0f);
	
	private static final Map<String, Weather> LOOKUP = Maps.newHashMap();

	private final boolean downfall;
	private final boolean dark;
	private final float temperature;
	private final float fog;
	private final String name;
	private final String display;
	
	private static class RngWeather extends RngItem {
		private static final WeightedList<RngWeather>[] LISTS = new WeightedList[4];
		
		static {
			for(int z = 0; z < LISTS.length; z++) {
				LISTS[z] = new WeightedList<RngWeather>();
			}
		}
		
		private final Weather weather;
		
		private RngWeather(Weather weather, int weight) {
			super(weight);
			this.weather = weather;
		}
	}
	
	private Weather(String name, String display, float temp, float fog, int ... chances) {
		this(name, display, false, false, temp, fog, chances);
	}
	
	private Weather(String name, String display, boolean dark, float temp, float fog, int ... chances) {
		this(name, display, true, dark, temp, fog, chances);
	}
	
	private Weather(String name, String display, boolean downfall, boolean dark, float temp, float fog, int ... chances) {
		this.name = name;
		this.display = display;
		this.downfall = downfall;
		this.dark = dark;
		this.temperature = temp * 40.0f;
		this.fog = fog;
		for(int z = 0; chances.length > 0 && z < RngWeather.LISTS.length; z++) {
			int chance = z >= chances.length ? chances[0] : chances[z];
			if(chance > 0)
				RngWeather.LISTS[z].add(new RngWeather(this, chance));
		}
	}

	public int getID() {
		return this.ordinal();
	}

	public String getName() {
		return this.name;
	}

	public String toString() {
		return this.name;
	}

	public String getDisplay() {
		return this.display;
	}

	public boolean hasDownfall() {
		return this.downfall;
	}

	public boolean hasThunder() {
		return this.dark;
	}

	public boolean canRain() {
		return this.temperature < 100.0f;
	}

	public boolean isDark() {
		return this.dark;
	}

	public float getTemperature() {
		return this.temperature;
	}

	public float getFogIntensity() {
		return this.fog;
	}

	public static Weather getByID(int id) {
		if(id >= 0 && id < values().length)
			return values()[id];
		return CLEAR;
	}

	public static Weather getByName(String name) {
		return LOOKUP.get(name.toLowerCase());
//		return type == null ? CLEAR : type;
//		for(Weather weather : values()) {
//			if(("" + weather.getID()).equals(name) || weather.getName().equalsIgnoreCase(name)) {
////					|| weather.getName().substring(0, 1).equalsIgnoreCase(name)) {
//				return weather;
//			}
//		}
//		return null;
	}
	
	static {
		for(Weather type : values()) {
			LOOKUP.put(type.name, type);
		}
	}
	
	public static Weather pick(float temp, Random rand) {
		temp = World.ABSOLUTE_ZERO + temp;
		return RngWeather.LISTS[temp <= 0.0f ? 3 : (temp <= 12.5f ? 2 : (temp <= 25.0f ? 0 : 1))].pick(rand).weather;
	}
}