package speiger.src.coreengine.assets.language;

import java.util.Map;

import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;

import speiger.src.collections.objects.maps.impl.hash.Object2ObjectOpenHashMap;
import speiger.src.collections.objects.utils.maps.Object2ObjectMaps;
import speiger.src.coreengine.assets.AssetLocation;
import speiger.src.coreengine.assets.AssetManager;
import speiger.src.coreengine.assets.base.MultiAsset;
import speiger.src.coreengine.assets.reloader.IReloadableResource;

public class LanguageManager implements IReloadableResource {
	final AssetLocation location = AssetLocation.of("lang");
	Map<String, Language> languages = new Object2ObjectOpenHashMap<>();
	AssetManager assets;
	String currentLanguage;
	
	@Override
	public void reload() {
		languages.clear();
		try(MultiAsset langs = assets.getAllAssets(location.subAsset("langs.json"))) {
			for(int i = 0,m = langs.size();i < m;i++) {
				preLoadLanguage(langs.get(i).json());
			}
		}
		catch(Exception e) {
			e.printStackTrace();
		}
		if(loadLanguage(currentLanguage)) {
			I18n.CURRENT_LANGUAGE = languages.get(currentLanguage);
		}
		else {
			Language dummy = new Language("en_US", "English");
			dummy.load(Object2ObjectMaps.empty());
			I18n.CURRENT_LANGUAGE = dummy;
		}
	}
	
	public boolean setLanguage(String lang) {
		if(loadLanguage(lang)) {
			I18n.CURRENT_LANGUAGE = languages.get(lang);
			Language currentLang = languages.get(currentLanguage);
			currentLanguage = lang;
			if(currentLang != null) currentLang.clear();
			return true;
		}
		return false;
	}
	
	protected boolean loadLanguage(String loadingLang) {
		Language lang = languages.get(loadingLang);
		if(lang == null) return false;
		Map<String, String> map = new Object2ObjectOpenHashMap<>();
		loadLanguage(loadingLang, map);
		if(loadingLang != "en_US") loadLanguage("en_US", map); 
		lang.load(map);
		return true;
	}
	
	protected void loadLanguage(String lang, Map<String, String> data) {
		try(MultiAsset language = assets.getAllAssets(location.subAsset(lang+".lang"))) {
			for(int i = 0,m = language.size();i < m;i++) {
				try {
					for(Map.Entry<String, JsonElement> element : language.get(i).json().entrySet()) {
						loadEntry(element.getKey(), element.getValue(), data);
					}
				}
				catch(Exception e) {
					e.printStackTrace();
				}
			}
		}
		catch(Exception e) {
			e.printStackTrace();
		}
	}
	
	protected void loadEntry(String basePath, JsonElement el, Map<String, String> data) {
		if(el.isJsonPrimitive()) data.putIfAbsent(basePath, el.getAsString());
		else if(el.isJsonObject()) {
			for(Map.Entry<String, JsonElement> elements : el.getAsJsonObject().entrySet()) {
				String key = elements.getKey();
				if(key.isEmpty()) loadEntry(basePath, elements.getValue(), data);
				else loadEntry(basePath+"."+key, elements.getValue(), data);
			}
		}
	}
	
	protected void preLoadLanguage(JsonObject object) {
		JsonArray array = object.getAsJsonArray("languages");
		if(array == null) return;
		for(int i = 0,m = array.size();i < m;i++) {
			JsonArray subArray = array.get(i).getAsJsonArray();
			if(subArray.size() != 2) continue;
			String key = subArray.get(0).getAsString();
			String value = subArray.get(1).getAsString();
			if(key.length() != 2 || value.length() > 16) continue;
			languages.computeIfAbsent(key, _ -> new Language(key, value));
		}
	}
	
}
