package de.champonthis.buntspecht.i18n.businesslogic;

import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.Map.Entry;
import java.util.stream.Collectors;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.SmartInitializingSingleton;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import com.google.gson.Gson;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;

import de.champonthis.buntspecht.i18n.model.I18n;
import de.champonthis.buntspecht.i18n.repository.I18nRepository;


@Component
public class I18nManager implements SmartInitializingSingleton {

	private Logger logger = LoggerFactory.getLogger(I18nManager.class);

	@Autowired
	private I18nRepository i18nRepository;

	@Autowired
	private ResourceLoader resourceLoader;

	private Gson gson = new Gson();

	
	public I18n get(String locale) {
		return i18nRepository.findById(locale).orElse(null);
	}

	
	public JsonObject getLabel(String locale) {
		I18n i18n = get(locale);
		if (i18n != null && StringUtils.hasText(i18n.getLabel())) {
			JsonElement element = JsonParser.parseString(i18n.getLabel());
			if (element != null && element.isJsonObject()) {
				return element.getAsJsonObject();
			}
		}

		return null;
	}

	
	public List<String> getLocales() {
		return i18nRepository.findAll().stream().map(I18n::getLocale).collect(Collectors.toList());
	}

	
	protected void extendJsonObject(JsonObject dest, JsonObject src) {
		for (Entry<String, JsonElement> srcEntry : src.entrySet()) {
			String srcKey = srcEntry.getKey();
			JsonElement srcValue = srcEntry.getValue();
			if (dest.has(srcKey)) {
				JsonElement destValue = dest.get(srcKey);
				if (destValue.isJsonObject() && srcValue.isJsonObject()) {
					extendJsonObject(destValue.getAsJsonObject(), srcValue.getAsJsonObject());
				} else {
					dest.add(srcKey, srcValue);
				}
			} else {
				dest.add(srcKey, srcValue);
			}
		}
	}

	
	public I18n addLabel(String locale, JsonObject newLabel) {
		JsonObject label = getLabel(locale);

		if (label == null || label.size() == 0 || label.entrySet().isEmpty()) {
			label = newLabel;
		} else {
			extendJsonObject(label, newLabel);
		}

		I18n i18n = new I18n();
		i18n.setLocale(locale);
		i18n.setLabel(gson.toJson(label));

		return i18nRepository.save(i18n);
	}

	
	public I18n setLabel(String locale, JsonObject label) {
		I18n i18n = new I18n();
		i18n.setLocale(locale);
		i18n.setLabel(gson.toJson(label));

		return i18nRepository.save(i18n);
	}

	
	public void deleteLabel(String locale) {
		if (i18nRepository.existsById(locale)) {
			i18nRepository.deleteById(locale);
		}
	}

	/*
	 * @see org.springframework.beans.factory.SmartInitializingSingleton#
	 * afterSingletonsInstantiated()
	 */
	@Override
	public void afterSingletonsInstantiated() {
		try {
			Resource resource = resourceLoader.getResource("classpath:label");

			if (resource.exists()) {
				File labelFolder = resource.getFile();
				if (labelFolder.exists() && labelFolder.isDirectory()) {
					for (File labelFile : labelFolder.listFiles()) {
						JsonObject label = JsonParser.parseReader(new FileReader(labelFile, StandardCharsets.UTF_8))
								.getAsJsonObject();

						String locale = labelFile.getName().replace(".json", "");
						addLabel(locale, label);
					}
				}
			}

		} catch (IOException e) {
			logger.warn("cannot read in label folder", e.getMessage());
		}
	}

}
