package speiger.src.coreengine.rendering.guiOld.renderer.provider;

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

import com.google.gson.JsonObject;

import speiger.src.collections.objects.lists.ObjectArrayList;
import speiger.src.collections.objects.maps.impl.hash.Object2FloatLinkedOpenHashMap;
import speiger.src.collections.objects.maps.impl.hash.Object2ObjectLinkedOpenHashMap;
import speiger.src.collections.objects.maps.impl.hash.Object2ObjectOpenHashMap;
import speiger.src.collections.objects.maps.interfaces.Object2FloatMap;
import speiger.src.collections.objects.maps.interfaces.Object2FloatMap.Entry;
import speiger.src.collections.objects.utils.maps.Object2FloatMaps;
import speiger.src.coreengine.assets.AssetLocation;
import speiger.src.coreengine.assets.AssetManager;
import speiger.src.coreengine.assets.base.IAsset;
import speiger.src.coreengine.assets.reloader.IReloadableResource;
import speiger.src.coreengine.rendering.guiOld.renderer.FontRenderer;

public class FontManager implements IReloadableResource
{
	Map<AssetLocation, FontRenderer> fontRenders = new Object2ObjectLinkedOpenHashMap<>();
	Object2FloatMap<AssetLocation> fontSizes = new Object2FloatLinkedOpenHashMap<>();
	Map<String, IFontLoader> loaders = new Object2ObjectOpenHashMap<>(); 
	
	AssetManager manager;
	
	public FontManager()
	{
		registerFontLoader("bitmap", BitmapFontProvider::load);
		registerFontLoader("java-ttf", BitmapFontProvider::create);
	}
	
	public void setAssetManager(AssetManager manager)
	{
		this.manager = manager;
	}
	
	public void registerFontLoader(String id, IFontLoader provider)
	{
		loaders.put(id, provider);
	}
	
	public FontRenderer loadFont(AssetLocation location, float desiredSize)
	{
		FontRenderer render = fontRenders.get(location);
		if(render == null)
		{
			IFontProvider provider = loadProvider(location, desiredSize);
			if(provider != null)
			{
				render = new FontRenderer();
				render.setProvider(provider);
				fontRenders.put(location, render);
				fontSizes.putIfAbsent(location, desiredSize);
			}
		}
		return render;
	}
	
	private IFontProvider loadProvider(AssetLocation location, float desiredSize)
	{
		try(IAsset asset = manager.getAsset(location))
		{
			JsonObject obj = asset.json();
			IFontLoader loader = loaders.get(obj.get("type").getAsString());
			if(loader == null) return null;
			return loader.create(obj, desiredSize, manager);
		}
		catch(Exception e) { e.printStackTrace(); }
		return null;
	}
	
	public static interface IFontLoader
	{
		public IFontProvider create(JsonObject obj, float desiredSize, AssetManager loader);
	}

	@Override
	public void reload()
	{
		List<IFontProvider> providers = new ObjectArrayList<>();
		for(Entry<AssetLocation> entry : Object2FloatMaps.fastIterable(fontSizes))
		{
			AssetLocation location = entry.getKey();
			FontRenderer font = fontRenders.get(location);
			providers.add(font.getProvider());
			font.setProvider(loadProvider(location, entry.getFloatValue()));
		}
		for(int i = 0,m=providers.size();i<m;providers.get(i++).destroy());
	}
	
	@Override
	public void destroy()
	{
		fontRenders.values().forEach(FontRenderer::destory);
		fontRenders.clear();
	}
}