/**
 *                                                                            
 * Copyright (c) 2011, 2016 - Loetz GmbH&Co.KG (69115 Heidelberg, Germany)
 *                                                                            
 * All rights reserved. This program and the accompanying materials           
 * are made available under the terms of the Eclipse Public License 2.0        
 * which accompanies this distribution, and is available at                  
 * https://www.eclipse.org/legal/epl-2.0/                                 
 *                                 
 * SPDX-License-Identifier: EPL-2.0                                 
 *                                                                            
 * Contributors:   
 * Christophe Loetz (Loetz GmbH&Co.KG) - initial implementation 
 * 
 * 
 *  This copyright notice shows up in the generated Java code
 *
 */
 
package org.eclipse.osbp.xtext.i18n

//import com.google.api.GoogleAPI
//import com.google.api.translate.Language
//import com.google.api.translate.Translate
import java.util.Comparator
import java.util.HashMap
import java.util.Properties
import java.util.TreeMap
import org.apache.commons.lang3.StringEscapeUtils
import org.eclipse.emf.ecore.EObject
import org.eclipse.emf.ecore.resource.Resource
import org.eclipse.osbp.preferences.ProductConfiguration
import org.eclipse.osbp.xtext.addons.AdvancedJvmModelGenerator
import org.eclipse.osbp.xtext.addons.EObjectHelper
import org.eclipse.xtext.RuleCall
import org.eclipse.xtext.generator.AbstractFileSystemAccess2
import org.eclipse.xtext.generator.IFileSystemAccess
import org.eclipse.xtext.nodemodel.util.NodeModelUtils

class StringComparator implements Comparator<String> {
	override compare(String arg0, String arg1) {
		if (arg0 < arg1) {
			return -1
		} else if (arg0 > arg1) {
			return 1
		} else {
			return 0
		}
	}
}

class I18NModelGenerator extends AdvancedJvmModelGenerator {

	protected var properties = <String, String>newTreeMap(new StringComparator())
	protected var addedTranslatables = <String, String>newHashMap

	def addTranslatables(String additionals) {
		// additionals are expected as comma separated list, pairs in list are expected to be separated by "->"
		addedTranslatables.clear
		var pairs = additionals.split(",")
		for (pair : pairs) {
			if (pair.contains("->")) {
				var parts = pair.split("->")
				var iter = parts.iterator
				addedTranslatables.put(iter.next, iter.next)
			} else {
				addedTranslatables.put(pair, null)
			}
		}
	}

	def getTranslatables(Resource resource, TreeMap<String, String> translatables) {
		translatables.clear

		// add static translatables
		for (additional : addedTranslatables.keySet) {
			if (additional.contains(":")) {
				var complex = additional.split(":")
				translatables.put(I18NKeyGenerator.key(complex.get(1)), I18NKeyGenerator.value(complex.get(1)))
			} else {
				translatables.put(I18NKeyGenerator.key(additional), I18NKeyGenerator.value(additional))
			}
		}
		var EObject eobject = EObjectHelper.getSemanticElement(resource)
		var node = NodeModelUtils.getNode(eobject)
		var contentsIterator = node.asTreeIterable.iterator
		while (contentsIterator.hasNext) {
			var abstractNode = contentsIterator.next

			// find all translatables
			if (abstractNode.grammarElement instanceof RuleCall) {
				var rule = abstractNode.grammarElement as RuleCall
				if (rule.rule.name.startsWith(I18nUtil.TRANSLATABLE)) {
					var found = false
					while (contentsIterator.hasNext && !found) {
						abstractNode = contentsIterator.next
						if (abstractNode.grammarElement instanceof RuleCall) {
							var text = new StringBuffer();
							for (leaf : abstractNode.leafNodes) {
								text.append(leaf.text.trim)
							}
							if (text.toString.contains("extends") || text.toString.contains("mapped superclass")) {
								found = true;
							} else if (text.toString.length > 0 && !text.toString.equals("\"\"")) {
								translatables.put(I18NKeyGenerator.key(text.toString),
									I18NKeyGenerator.value(text.toString))
							}
							found = true
						}
					}
				}
			}
		}
	}

	def void generateI18n(IFileSystemAccess fsa, Resource input) {
		if (ProductConfiguration.willLanguagesAutocreate) {
			if (fsa instanceof AbstractFileSystemAccess2) {
				var erfsa = fsa as AbstractFileSystemAccess2
				var translations = <String, TreeMap<String, String>>newHashMap

				var supportedLanguages = ProductConfiguration.getLanguages()
				properties.clear
				getTranslatables(input, properties)

				for (localeId : supportedLanguages.keySet) {
					val Properties prop = new Properties()
					try {
						if (localeId.equals("default")) {
							prop.load(
								erfsa.readBinaryFile("I18N.properties",
									DSLOutputConfigurationProvider.DEFAULT_OUTPUT_I18N))
						} else {
							prop.load(
								erfsa.readBinaryFile("I18N_" + localeId + ".properties",
									DSLOutputConfigurationProvider.DEFAULT_OUTPUT_I18N))
						}
					} catch (Exception e) {
						e.stackTrace
					}
					var p = <String, String>newTreeMap(new StringComparator())
					translations.put(localeId, p);

					// remove untranslated entries
					for (props : prop.stringPropertyNames) {
						if (prop.getProperty(props).length > 0) {
							p.put(props, prop.getProperty(props))
						}
					}

					// add new key to default
					if (localeId.equals("default")) {
						for (props : properties.keySet) {
							translations.get("default").put(props, properties.get(props))
						}
					}
				}

				// try to translate it
				// identify to google's billing service for translations
//				GoogleAPI.setHttpReferrer(ProductConfiguration.languagesGoogleHttpReferrer)
//				GoogleAPI.setKey(ProductConfiguration.languagesGoogleApiKey)

				for (localeId : supportedLanguages.keySet) {
					if (!localeId.equals("default")) {

						// get google's language enumeration
//						var googleLanguage = Language.fromString(supportedLanguages.get(localeId).getLanguage())

						// insert new keys
						for (key : translations.get("default").keySet) {
							if (!findTranslation(localeId, key, translations)) {

								// auto translate
								var value = translations.get("default").get(key)

								// we split numbers from text for better translation results
								var payLoads = improveForTranslation(value)

								// as we use english model definitions, the original can be used as translation
								if (localeId.equals("en")) {
									translations.get(localeId).put(key, payLoads.join);
								} else if (ProductConfiguration.languagesAutotranslate) { // if auto translation is enabled
									var property = ""

									// rearrange text and numbers again
									for (payLoad : payLoads) {
										if (Character.isLetter(payLoad.charAt(0))) {
											// use java utf-8 escape sequences
											property = property + StringEscapeUtils.escapeJava(payLoad
//												Translate.DEFAULT.execute(payLoad, Language.ENGLISH, googleLanguage)
												)
										} else {
											property = property + payLoad
										}
									}

									translations.get(localeId).put(key, property)
								} else if (!ProductConfiguration.languagesAutotranslate) { // if auto translation is disabled, copy english to german as default
									// TODO (JCD): Only for test purposes. To avoid the auto creation of the german translation values.
//									if (localeId.equals("de")) {
//										translations.get(localeId).put(key, payLoads.join);
//									}
								}
							}
						}
					}
				}

				// write out
				for (localeId : supportedLanguages.keySet) {
					var output = new StringBuilder()
					output.append("#" + localeId + "\n")
					for (key : translations.get(localeId).keySet) {
						var value = translations.get(localeId).get(key)
						// only ISO8859-1 is allowed inside the property values, thus always escape the text!!!
						value = StringEscapeUtils.escapeJava(value)
						output.append(key + "=" + value).append("\n")
					}
					if (localeId.equals("default")) {
						erfsa.generateFile("I18N.properties", DSLOutputConfigurationProvider.DEFAULT_OUTPUT_I18N, output)
					} else {
						erfsa.generateFile("I18N_" + localeId + ".properties",
							DSLOutputConfigurationProvider.DEFAULT_OUTPUT_I18N, output)
					}
				}
			}
		}
	}

	def boolean findTranslation(String localeId, String key, HashMap<String, TreeMap<String, String>> translations) {
		// find translations recursive until base language is reached - 
		// assumption: variants and countries can fall back to base language
		// de_AT_X
		var splitter = localeId.split("_")
		if (splitter.length > 1) {
			var part = <String>newArrayList(splitter)
			part.remove(part.size - 1)
			if (findTranslation(part.join("_"), key, translations)) {
				return true
			}
		}
		if (translations.containsKey(localeId) && translations.get(localeId).containsKey(key)) {
			return true
		}
		return false
	}

	def splitTextAndNumbers(String text) {
		var array = <String>newArrayList
		if (text === null || text.length == 0) {
			return array
		}
		var current = ""
		var len = text.length
		var i = 1
		var lastChar = text.charAt(0)
		current = current + lastChar
		while (i < len) {

			// detect gap
			if (Character.isLetter(text.charAt(i)) && Character.isDigit(lastChar) ||
				Character.isDigit(text.charAt(i)) && Character.isLetter(lastChar)) {
				array.add(current)
				current = ""
			}
			lastChar = text.charAt(i)
			current = current + lastChar
			i = i + 1
		}
		if (current.length > 0) {
			array.add(current)
		}
		return array
	}

	def improveForTranslation(String key) {
		var payLoad = key.replace("_", " ")

		//payLoad = payLoad.replaceAll("^m ", "")
		var newArray = <String>newArrayList
		var array = splitTextAndNumbers(payLoad)
		for (element : array) {
			if (Character.isLetter(element.charAt(0))) {
				newArray.add(deAbbreviateTranslation(element))
			} else {
				newArray.add(element)
			}
		}
		// capitalize first letter in english
		if(newArray.size > 0) {
			newArray.set(0, newArray.get(0).toFirstUpper)
		}
		return newArray
	}

	def deAbbreviateTranslation(String text) {
		var payLoad = text

		// known abbreviations
		payLoad = payLoad.replaceAll("(^|\\s)abv(\\s|$)", " alcohol by volume ")
		payLoad = payLoad.replaceAll("(^|\\s)abw(\\s|$)", " alcohol by weight ")
		payLoad = payLoad.replaceAll("(^|\\s)accnt(\\s|$)", " account ")
		payLoad = payLoad.replaceAll("(^|\\s)addr(\\s|$)", " address ")
		payLoad = payLoad.replaceAll("(^|\\s)base id(\\s|$)", " identifier ")
		payLoad = payLoad.replaceAll("(^|\\s)base uuid(\\s|$)", " identifier ")
		payLoad = payLoad.replaceAll("(^|\\s)bsin(\\s|$)", " brand single identification number ")
		payLoad = payLoad.replaceAll("(^|\\s)cal(\\s|$)", " calories ")
		payLoad = payLoad.replaceAll("(^|\\s)carb(\\s|$)", " carbohydrate ")
		payLoad = payLoad.replaceAll("(^|\\s)chol(\\s|$)", " cholesterol ")
		payLoad = payLoad.replaceAll("(^|\\s)cd(\\s|$)", " code ")
		payLoad = payLoad.replaceAll("(^|\\s)desc(\\s|$)", " description ")
		payLoad = payLoad.replaceAll("(^|\\s)diet(\\s|$)", " dietary ")
		payLoad = payLoad.replaceAll("(^|\\s)dv(\\s|$)", " daily volume ")
		payLoad = payLoad.replaceAll("(^|\\s)exp(\\s|$)", " expiring ")
		payLoad = payLoad.replaceAll("(^|\\s)hdr(\\s|$)", " header ")
		payLoad = payLoad.replaceAll("(^|\\s)hier(\\s|$)", " hierarchy ")
		payLoad = payLoad.replaceAll("(^|\\s)id(\\s|$)", " identifier ")
		payLoad = payLoad.replaceAll("(^|\\s)img(\\s|$)", " image ")
		payLoad = payLoad.replaceAll("(^|\\s)lang(\\s|$)", " language ")
		payLoad = payLoad.replaceAll("(^|\\s)nm(\\s|$)", " name ")
		payLoad = payLoad.replaceAll("(^|\\s)num(\\s|$)", " number ")
		payLoad = payLoad.replaceAll("(^|\\s)pkg(\\s|$)", " package ")
		payLoad = payLoad.replaceAll("(^|\\s)ref(\\s|$)", " reference ")
		payLoad = payLoad.replaceAll("(^|\\s)sat(\\s|$)", " saturated ")
		payLoad = payLoad.replaceAll("(^|\\s)serv(\\s|$)", " serving ")
		payLoad = payLoad.replaceAll("(^|\\s)sod(\\s|$)", " sodium ")
		payLoad = payLoad.replaceAll("(^|\\s)sku(\\s|$)", " stock-keeping unit ")
		payLoad = payLoad.replaceAll("(^|\\s)srp(\\s|$)", " suggested retail price ")
		payLoad = payLoad.replaceAll("(^|\\s)tel(\\s|$)", " telephone ")
		payLoad = payLoad.replaceAll("(^|\\s)tot(\\s|$)", " total ")
		payLoad = payLoad.trim
		return payLoad
	}

	override doGenerate(Resource input, IFileSystemAccess fsa) {
		// create i18n property files
		fsa.generateI18n(input)
		super.doGenerate(input, fsa)
	}
}
