package net.robertboehm.ld22;

import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.util.HashMap;
import java.util.Map;

import org.newdawn.slick.Image;
import org.newdawn.slick.Music;
import org.newdawn.slick.SlickException;

public class GameAssets {

	private static final String[] preloadedImages = new String[] { "player",
			"steve", "tom", "tiles" };

	private static final String IMAGE_FORMAT = "/assets/%s.png";
	private static final String TILEPROPERTIES_FORMAT = "/assets/%s.txt";
	private static final String MAP_FORMAT = "/maps/%s.dat";
	private static final String MAPGRID_FORMAT = "/mapgrids/%s.dat";
	private static final String MAPTILE_FORMAT = "%s_%d";
	private static final String SCRIPT_FORMAT = "/scripts/%s.txt";

	private static final String DEFAULT_TILESET = "tiles";
	private static final String ASSETNAME_PLAYER = "player";
	
	public static Music music = null;

	private static final Map<String, Image> images = new HashMap<String, Image>();

	private static final Map<String, GameCharset> charsets = new HashMap<String, GameCharset>();
	private static final Map<String, GameMap> maps = new HashMap<String, GameMap>();
	private static final Map<String, Mapgrid> mapgrids = new HashMap<String, Mapgrid>();
	private static final Map<String, GameTileset> tilesets = new HashMap<String, GameTileset>();
	private static final Map<String, TileProperties> tileproperties = new HashMap<String, TileProperties>();

	private GameAssets() {
	};
	
	public static void stopMusic() {
		if(music != null) {
			music.stop();
		}
	}
	
	public static void playMusic() {
		if(music != null) {
			music.loop(1f, AreYouStillThere.volume / 3);
		}
	}

	public static void refreshVolume() {
		if(music != null) {
			music.setVolume(AreYouStillThere.volume / 3);
		}
	}

	public static void preloadImages() {
		for (String s : preloadedImages) {
			getImage(s);
		}
		try {
			music = new Music(GameAssets.class.getResource("/assets/music.ogg"));
		} catch (Exception e) {}
	}

	public static Image getImage(String name) {
		if (!images.containsKey(name)) {
			try {
				images.put(name, new Image(
						getResourceStream(IMAGE_FORMAT, name), name, false,
						Image.FILTER_NEAREST)
						.getScaledCopy(AreYouStillThere.ZOOM));
			} catch (SlickException e) {
				e.printStackTrace();
			}
		}
		return images.get(name);
	}

	public static InputStream getResourceStream(String format, Object... args) {
		return GameAssets.class
				.getResourceAsStream(String.format(format, args));
	}

	public static GameCharset getPlayerCharset() {
		return getCharset(ASSETNAME_PLAYER);
	}

	public static GameCharset getCharset(String name) {
		if (!charsets.containsKey(name)) {
			charsets.put(name, new GameCharset(getImage(name)));
		}
		return charsets.get(name);
	}

	public static GameMap getMap(String name) {
		if (!maps.containsKey(name)) {
			try {
				maps.put(name, StreamedGameMap.fromStream(name, getTileset(),
						getResourceStream(MAP_FORMAT, name)));
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return maps.get(name);
	}

	public static GameMap getMap(String mapgrid, int mapid) {
		return getMap(String.format(MAPTILE_FORMAT, mapgrid, mapid));
	}

	public static GameTileset getTileset() {
		return getTileset(DEFAULT_TILESET);
	}

	public static GameTileset getTileset(String name) {
		if (!tilesets.containsKey(name)) {
			tilesets.put(name, new GameTileset(getImage(name),
					getTileProperties(name)));
		}
		return tilesets.get(name);
	}

	public static Mapgrid getMapgrid(String name) {
		if (!mapgrids.containsKey(name)) {
			try {
				mapgrids.put(name, StreamedMapGrid.fromStream(new MapProvider(
						name), getResourceStream(MAPGRID_FORMAT, name)));
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return mapgrids.get(name);
	}

	public static TileProperties getTileProperties(String name) {
		if (!tileproperties.containsKey(name)) {
			try (InputStreamReader isr = new InputStreamReader(
					getResourceStream(TILEPROPERTIES_FORMAT, name))) {
				tileproperties.put(name, new TileProperties(isr));
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return tileproperties.get(name);
	}

	public static Reader getScript(String name) {
		return new InputStreamReader(getResourceStream(SCRIPT_FORMAT, name));
	}

}
