package com.inepex.ineom.server;

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

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.inject.Inject;
import com.google.inject.Provider;
import com.inepex.inei18n.shared.CurrentLang;
import com.inepex.ineom.shared.descriptor.DescriptorBase;
import com.inepex.ineom.shared.descriptor.ObjectDesc;
import com.inepex.ineom.shared.descriptor.fdesc.FDesc;
import com.inepex.ineom.shared.descriptorstore.ClientDescriptorStore;
import com.inepex.ineom.shared.descriptorstore.DescriptorStore;

public class MultiLangDescStore extends DescriptorStore {
	
	private static final Logger _logger = LoggerFactory.getLogger(MultiLangDescStore.class);
	
	private final Map<String, DescriptorStore> storeByLang = new HashMap<String, DescriptorStore>();
	private final Provider<CurrentLang> currLangProvider;
	private DescStoreCreator descStoreCreator;
	
	@Inject
	public MultiLangDescStore(Provider<CurrentLang> currLangProvider, DescStoreCreator descStoreCreator) {
		this.currLangProvider = currLangProvider;
		this.descStoreCreator=descStoreCreator;
	}
	
	public DescriptorStore get(String lang) {
		synchronized (storeByLang) {
			if (!storeByLang.containsKey(lang)){
				_logger.info("MultiDescStore has just created desc store for lang: {}", lang);
				ClientDescriptorStore localizedDescStore = descStoreCreator.createDescStore(lang);
				storeByLang.put(lang, localizedDescStore);
			}
			return storeByLang.get(lang);	
		}		
	}
	
	public String currentLang() {
		try {
			return currLangProvider.get().getCurrentLang();
		} catch (Exception e) {
			_logger.warn("Lang can not found:", e);
			return CurrentLang.DEFAULT_LANG;
		}
	}

	// Bridge methods follow
	
	@Override
	public ObjectDesc getOD(String objectDescriptorName) {
		return getCurrentDescriptorStore().getOD(objectDescriptorName);
	}


	@Override
	public void registerObjectDesc(Marker marker, ObjectDesc descriptor) {
		getCurrentDescriptorStore().registerObjectDesc(marker, descriptor);
	}

	@Override
	public FDesc getRelatedFieldDescrMultiLevel(ObjectDesc baseOD, List<String> path) {
		return getCurrentDescriptorStore().getRelatedFieldDescrMultiLevel(baseOD, path);
	}

	@Override
	public <D extends DescriptorBase> D getNamedTypedDesc(String objDescName, String namedDescName, Class<D> clazz) {
		return getCurrentDescriptorStore().getNamedTypedDesc(objDescName, namedDescName, clazz);
	}

	@Override
	public <D extends DescriptorBase> void addNamedTypedDesc(Marker marker, String objDescName, String namedDescName, D namedDesc) {
		getCurrentDescriptorStore().addNamedTypedDesc(marker, objDescName, namedDescName, namedDesc);
	}

	@Override
	public void registerDescriptors(Marker marker, ObjectDesc descriptor, DescriptorBase... defaultDescriptors) {
		getCurrentDescriptorStore().registerDescriptors(marker, descriptor, defaultDescriptors);
	}
	
	public DescriptorStore getCurrentDescriptorStore(){
		return get(currentLang());
	}

	@Override
	public String getOdNames(Decoration decorator) {
		StringBuilder sb = new StringBuilder();
		for(String lang : storeByLang.keySet()) {
			if(sb.length()>0) {
				switch (decorator) {
				case html:
					sb.append("<br /><br />");
					break;
				case javaNewLine:
				default:
					sb.append("\n");
					break;
				}
			}
			sb.append(lang);
			sb.append(": (");
			sb.append(storeByLang.get(lang).getOdNames(decorator));
			sb.append(")");
		}
		
		return sb.toString();
	}
	
	public Map<String, DescriptorStore> getStoreByKey() {
		return storeByLang;
	}
}


@@ -97,16 +97,63 @@
 til.Map;
+%0Aimport java.util.concurrent.ConcurrentHashMap;
 %0A%0Aimport
@@ -787,16 +787,30 @@
 e final 
+ConcurrentHash
 Map%3CStri
@@ -848,16 +848,26 @@
 g = new 
+Concurrent
 HashMap%3C
@@ -1242,16 +1242,101 @@
 lang) %7B%0A
+%09%09if (storeByLang.containsKey(lang))%7B%0A%09%09%09return storeByLang.get(lang);%0A%09%09%7D else %7B%09%09%0A%09
 %09%09synchr
@@ -1361,16 +1361,17 @@
 g) %7B%0A%09%09%09
+%09
 if (!sto
@@ -1399,16 +1399,17 @@
 lang))%7B%0A
+%09
 %09%09%09%09_log
@@ -1479,24 +1479,25 @@
 %7B%7D%22, lang);%0A
+%09
 %09%09%09%09ClientDe
@@ -1575,16 +1575,17 @@
 g);%0A%09%09%09%09
+%09
 storeByL
@@ -1622,18 +1622,20 @@
 re);%0A%09%09%09
+%09
 %7D%0A
+%09
 %09%09%09retur
@@ -1663,15 +1663,21 @@
 g);%09
-%0A
+%09%0A%09
 %09%09%7D%09%09%0A
+%09%09%7D%0A
 %09%7D%0A%09

add syncronization to MultiLangDescStore