/**
 * 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 java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
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.osbp.xtext.i18n.DSLOutputConfigurationProvider;
import org.eclipse.osbp.xtext.i18n.I18NKeyGenerator;
import org.eclipse.osbp.xtext.i18n.I18nUtil;
import org.eclipse.osbp.xtext.i18n.StringComparator;
import org.eclipse.xtext.RuleCall;
import org.eclipse.xtext.generator.AbstractFileSystemAccess2;
import org.eclipse.xtext.generator.IFileSystemAccess;
import org.eclipse.xtext.nodemodel.BidiTreeIterator;
import org.eclipse.xtext.nodemodel.ICompositeNode;
import org.eclipse.xtext.nodemodel.ILeafNode;
import org.eclipse.xtext.nodemodel.INode;
import org.eclipse.xtext.nodemodel.util.NodeModelUtils;
import org.eclipse.xtext.xbase.lib.CollectionLiterals;
import org.eclipse.xtext.xbase.lib.Conversions;
import org.eclipse.xtext.xbase.lib.Exceptions;
import org.eclipse.xtext.xbase.lib.IterableExtensions;
import org.eclipse.xtext.xbase.lib.StringExtensions;

@SuppressWarnings("all")
public class I18NModelGenerator extends AdvancedJvmModelGenerator {
  protected TreeMap<String, String> properties = CollectionLiterals.<String, String>newTreeMap(new StringComparator());
  
  protected HashMap<String, String> addedTranslatables = CollectionLiterals.<String, String>newHashMap();
  
  public void addTranslatables(final String additionals) {
    this.addedTranslatables.clear();
    String[] pairs = additionals.split(",");
    for (final String pair : pairs) {
      boolean _contains = pair.contains("->");
      if (_contains) {
        String[] parts = pair.split("->");
        final String[] _converted_parts = (String[])parts;
        Iterator<String> iter = ((List<String>)Conversions.doWrapArray(_converted_parts)).iterator();
        this.addedTranslatables.put(iter.next(), iter.next());
      } else {
        this.addedTranslatables.put(pair, null);
      }
    }
  }
  
  public void getTranslatables(final Resource resource, final TreeMap<String, String> translatables) {
    translatables.clear();
    Set<String> _keySet = this.addedTranslatables.keySet();
    for (final String additional : _keySet) {
      boolean _contains = additional.contains(":");
      if (_contains) {
        String[] complex = additional.split(":");
        translatables.put(I18NKeyGenerator.key(complex[1]), I18NKeyGenerator.value(complex[1]));
      } else {
        translatables.put(I18NKeyGenerator.key(additional), I18NKeyGenerator.value(additional));
      }
    }
    EObject eobject = EObjectHelper.getSemanticElement(resource);
    ICompositeNode node = NodeModelUtils.getNode(eobject);
    BidiTreeIterator<INode> contentsIterator = node.getAsTreeIterable().iterator();
    while (contentsIterator.hasNext()) {
      {
        INode abstractNode = contentsIterator.next();
        EObject _grammarElement = abstractNode.getGrammarElement();
        if ((_grammarElement instanceof RuleCall)) {
          EObject _grammarElement_1 = abstractNode.getGrammarElement();
          RuleCall rule = ((RuleCall) _grammarElement_1);
          boolean _startsWith = rule.getRule().getName().startsWith(I18nUtil.TRANSLATABLE);
          if (_startsWith) {
            boolean found = false;
            while ((contentsIterator.hasNext() && (!found))) {
              {
                abstractNode = contentsIterator.next();
                EObject _grammarElement_2 = abstractNode.getGrammarElement();
                if ((_grammarElement_2 instanceof RuleCall)) {
                  StringBuffer text = new StringBuffer();
                  Iterable<ILeafNode> _leafNodes = abstractNode.getLeafNodes();
                  for (final ILeafNode leaf : _leafNodes) {
                    text.append(leaf.getText().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;
                }
              }
            }
          }
        }
      }
    }
  }
  
  public void generateI18n(final IFileSystemAccess fsa, final Resource input) {
    boolean _willLanguagesAutocreate = ProductConfiguration.willLanguagesAutocreate();
    if (_willLanguagesAutocreate) {
      if ((fsa instanceof AbstractFileSystemAccess2)) {
        AbstractFileSystemAccess2 erfsa = ((AbstractFileSystemAccess2) fsa);
        HashMap<String, TreeMap<String, String>> translations = CollectionLiterals.<String, TreeMap<String, String>>newHashMap();
        Map<String, Locale> supportedLanguages = ProductConfiguration.getLanguages();
        this.properties.clear();
        this.getTranslatables(input, this.properties);
        Set<String> _keySet = supportedLanguages.keySet();
        for (final String localeId : _keySet) {
          {
            final Properties prop = new Properties();
            try {
              boolean _equals = localeId.equals("default");
              if (_equals) {
                prop.load(
                  erfsa.readBinaryFile("I18N.properties", 
                    DSLOutputConfigurationProvider.DEFAULT_OUTPUT_I18N));
              } else {
                prop.load(
                  erfsa.readBinaryFile((("I18N_" + localeId) + ".properties"), 
                    DSLOutputConfigurationProvider.DEFAULT_OUTPUT_I18N));
              }
            } catch (final Throwable _t) {
              if (_t instanceof Exception) {
                final Exception e = (Exception)_t;
                e.getStackTrace();
              } else {
                throw Exceptions.sneakyThrow(_t);
              }
            }
            StringComparator _stringComparator = new StringComparator();
            TreeMap<String, String> p = CollectionLiterals.<String, String>newTreeMap(_stringComparator);
            translations.put(localeId, p);
            Set<String> _stringPropertyNames = prop.stringPropertyNames();
            for (final String props : _stringPropertyNames) {
              int _length = prop.getProperty(props).length();
              boolean _greaterThan = (_length > 0);
              if (_greaterThan) {
                p.put(props, prop.getProperty(props));
              }
            }
            boolean _equals_1 = localeId.equals("default");
            if (_equals_1) {
              Set<String> _keySet_1 = this.properties.keySet();
              for (final String props_1 : _keySet_1) {
                translations.get("default").put(props_1, this.properties.get(props_1));
              }
            }
          }
        }
        Set<String> _keySet_1 = supportedLanguages.keySet();
        for (final String localeId_1 : _keySet_1) {
          boolean _equals = localeId_1.equals("default");
          boolean _not = (!_equals);
          if (_not) {
            Set<String> _keySet_2 = translations.get("default").keySet();
            for (final String key : _keySet_2) {
              boolean _findTranslation = this.findTranslation(localeId_1, key, translations);
              boolean _not_1 = (!_findTranslation);
              if (_not_1) {
                String value = translations.get("default").get(key);
                ArrayList<String> payLoads = this.improveForTranslation(value);
                boolean _equals_1 = localeId_1.equals("en");
                if (_equals_1) {
                  translations.get(localeId_1).put(key, IterableExtensions.join(payLoads));
                } else {
                  boolean _isLanguagesAutotranslate = ProductConfiguration.isLanguagesAutotranslate();
                  if (_isLanguagesAutotranslate) {
                    String property = "";
                    for (final String payLoad : payLoads) {
                      boolean _isLetter = Character.isLetter(payLoad.charAt(0));
                      if (_isLetter) {
                        String _escapeJava = StringEscapeUtils.escapeJava(payLoad);
                        String _plus = (property + _escapeJava);
                        property = _plus;
                      } else {
                        property = (property + payLoad);
                      }
                    }
                    translations.get(localeId_1).put(key, property);
                  } else {
                    boolean _isLanguagesAutotranslate_1 = ProductConfiguration.isLanguagesAutotranslate();
                    boolean _not_2 = (!_isLanguagesAutotranslate_1);
                    if (_not_2) {
                    }
                  }
                }
              }
            }
          }
        }
        Set<String> _keySet_3 = supportedLanguages.keySet();
        for (final String localeId_2 : _keySet_3) {
          {
            StringBuilder output = new StringBuilder();
            output.append((("#" + localeId_2) + "\n"));
            Set<String> _keySet_4 = translations.get(localeId_2).keySet();
            for (final String key_1 : _keySet_4) {
              {
                String value_1 = translations.get(localeId_2).get(key_1);
                value_1 = StringEscapeUtils.escapeJava(value_1);
                output.append(((key_1 + "=") + value_1)).append("\n");
              }
            }
            boolean _equals_2 = localeId_2.equals("default");
            if (_equals_2) {
              erfsa.generateFile("I18N.properties", DSLOutputConfigurationProvider.DEFAULT_OUTPUT_I18N, output);
            } else {
              erfsa.generateFile((("I18N_" + localeId_2) + ".properties"), 
                DSLOutputConfigurationProvider.DEFAULT_OUTPUT_I18N, output);
            }
          }
        }
      }
    }
  }
  
  public boolean findTranslation(final String localeId, final String key, final HashMap<String, TreeMap<String, String>> translations) {
    String[] splitter = localeId.split("_");
    int _length = splitter.length;
    boolean _greaterThan = (_length > 1);
    if (_greaterThan) {
      ArrayList<String> part = CollectionLiterals.<String>newArrayList(splitter);
      int _size = part.size();
      int _minus = (_size - 1);
      part.remove(_minus);
      boolean _findTranslation = this.findTranslation(IterableExtensions.join(part, "_"), key, translations);
      if (_findTranslation) {
        return true;
      }
    }
    if ((translations.containsKey(localeId) && translations.get(localeId).containsKey(key))) {
      return true;
    }
    return false;
  }
  
  public ArrayList<String> splitTextAndNumbers(final String text) {
    ArrayList<String> array = CollectionLiterals.<String>newArrayList();
    if (((text == null) || (text.length() == 0))) {
      return array;
    }
    String current = "";
    int len = text.length();
    int i = 1;
    char lastChar = text.charAt(0);
    current = (current + Character.valueOf(lastChar));
    while ((i < len)) {
      {
        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 + Character.valueOf(lastChar));
        i = (i + 1);
      }
    }
    int _length = current.length();
    boolean _greaterThan = (_length > 0);
    if (_greaterThan) {
      array.add(current);
    }
    return array;
  }
  
  public ArrayList<String> improveForTranslation(final String key) {
    String payLoad = key.replace("_", " ");
    ArrayList<String> newArray = CollectionLiterals.<String>newArrayList();
    ArrayList<String> array = this.splitTextAndNumbers(payLoad);
    for (final String element : array) {
      boolean _isLetter = Character.isLetter(element.charAt(0));
      if (_isLetter) {
        newArray.add(this.deAbbreviateTranslation(element));
      } else {
        newArray.add(element);
      }
    }
    int _size = newArray.size();
    boolean _greaterThan = (_size > 0);
    if (_greaterThan) {
      newArray.set(0, StringExtensions.toFirstUpper(newArray.get(0)));
    }
    return newArray;
  }
  
  public String deAbbreviateTranslation(final String text) {
    String payLoad = text;
    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
  public void doGenerate(final Resource input, final IFileSystemAccess fsa) {
    this.generateI18n(fsa, input);
    super.doGenerate(input, fsa);
  }
}
