/*
 *  Copyright (C) 2013-2015 Stichting Akvo (Akvo Foundation)
 *
 *  This file is part of Akvo FLOW.
 *
 *  Akvo FLOW is free software: you can redistribute it and modify it under the terms of
 *  the GNU Affero General Public License (AGPL) as published by the Free Software Foundation,
 *  either version 3 of the License or any later version.
 *
 *  Akvo FLOW is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
 *  without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 *  See the GNU Affero General Public License included below for more details.
 *
 *  The full license text can also be seen at <http://www.gnu.org/licenses/agpl.html>.
 */

package services;

import java.io.File;
import java.io.FileInputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.commons.io.FileUtils;

public class TranslationGenerator {

    private static final Map<String, String> PATTERNS = new HashMap<String, String>();
    private static final Pattern ANCHOR = Pattern.compile("<a.*?>.*?</a>");
    private static final Pattern T_HELPER = Pattern.compile("\\{\\{t\\s\\_\\w+\\}\\}");
    private static final Pattern BINDING = Pattern.compile(">\\{\\{.*?\\}\\}<");
    private static final Pattern AKVO_ORG = Pattern.compile(">akvo.org</a>");

    static {
        PATTERNS.put("{{t ", "}}");
        PATTERNS.put("{{tooltip ", "}}");
        PATTERNS.put("promptBinding=\"Ember.STRINGS.", "\"");
        PATTERNS.put("placeholderBinding=\"Ember.STRINGS.", "\"");
        PATTERNS.put("String.loc('", "'");
        PATTERNS.put("(t> ", ")");
    }

    private static final String[] EXTS = {
            "handlebars", "js", "cljs"
    };

    public static void main(String[] args) throws Exception {

        if (args.length < 2) {
            System.err.println("<Dashboard> and <output> directories are required");
            return;
        }

        final File sources = new File(args[0]);
        final File output = new File(args[1]);

        final Properties ui_strings = new Properties();
        ui_strings.load(new FileInputStream(new File(output,
                "/ui-strings.properties")));

        final Map<String, String> trlKeys = new HashMap<String, String>();
        final List<String> enValues = new ArrayList<String>();

        for (File f : (List<File>) FileUtils.listFiles(sources, EXTS, true)) {
            if (f.getAbsolutePath().contains("vendor")
                    || f.getAbsolutePath().contains("plugins")
                    || f.getAbsolutePath().contains("tests")) {
                continue; // skipping
            }

            final List<String> lines = FileUtils.readLines(f, "UTF-8");
            int ln = 1;
            for (String line : lines) {
                if (containsTranslatableKeys(line)) {
                    final List<String> keys = getKeys(line);
                    if (!keys.isEmpty()) {
                        for (String k : keys) {
                            if (trlKeys.containsKey(k)) {
                                continue; // skip
                            }
                            final String en = ui_strings.getProperty(k);
                            if (en == null) {
                                System.err.println("Translation key `"
                                        + k
                                        + "` not found in ui-strings.properties");
                                ui_strings.put(k, "");
                            }

                            trlKeys.put(k, (en == null ? "" : en));

                            if (en != null && !"".equals(en)
                                    && !enValues.contains(en)) {
                                enValues.add(en);
                            }
                        }
                    }
                }
                if (f.getAbsolutePath().endsWith(".handlebars") &&
                        containsMissingTranslation(line)) {
                    System.err.println("Check for missing translation in " + f.getName() + ":" + ln
                            + " " + line);
                }
                ln++;
            }
        }

        Collections.sort(enValues);
        StringBuffer sb = new StringBuffer();
        for (String val : enValues) {
            sb.append(val.replaceAll(" ", "\\\\ ")).append(" = ").append(val)
                    .append("\n");
        }
        FileUtils.writeStringToFile(new File(output, "/en.properties"),
                sb.toString(), "ISO-8859-1");

        final List<String> tmp = new ArrayList<String>(trlKeys.keySet());
        Collections.sort(tmp);
        final StringBuffer uisource = new StringBuffer();
        for (String ui : tmp) {
            uisource.append(ui).append(" = ").append(trlKeys.get(ui))
                    .append("\n");
        }
        FileUtils.writeStringToFile(new File(output, "/ui-strings.properties"),
                uisource.toString(), "ISO-8859-1");
    }

    private static boolean containsMissingTranslation(String line) {
        final Matcher m = ANCHOR.matcher(line);
        if (!m.find()) {
            return false;
        }
        final Matcher m2 = T_HELPER.matcher(m.group());
        final Matcher m3 = BINDING.matcher(m.group());
        final Matcher m4 = AKVO_ORG.matcher(m.group()); // Hack to remove false positive
        if (!m2.find() && !m3.find() && !m4.find()) {
            return true;
        }
        return false;
    }

    private static boolean containsTranslatableKeys(String line) {
        for (String pattern : PATTERNS.keySet()) {
            if (line.contains(pattern)) {
                return true;
            }
        }
        return false;
    }

    private static List<String> getKeys(String line) {

        if (!containsTranslatableKeys(line)) {
            return Collections.emptyList();
        }

        final List<String> keys = new ArrayList<String>();
        for (String pattern : PATTERNS.keySet()) {
            keys.addAll(getKeysFromLine(line, pattern, PATTERNS.get(pattern)));
        }

        return keys;
    }

    private static List<String> getKeysFromLine(String line, String prefix,
            String suffix) {

        final List<String> keys = new ArrayList<String>();

        int start = line.indexOf(prefix);
        int end = -1;

        if (start != -1) {
            start += prefix.length();
            end = line.indexOf(suffix, start);
        }

        while (start > 0 && end > 0) {
            keys.add(line.substring(start, end));
            start = line.indexOf(prefix, end + 1);
            if (start == -1) {
                break;
            }
            start = start + prefix.length();
            end = line.indexOf(suffix, start);
        }

        return keys;
    }

}

@@ -1781,24 +1781,73 @@
 t%3E %22, %22)%22);%0A
+        PATTERNS.put(%22Ember.String.loc('%22, %22'%22);%0A
     %7D%0A%0A    p
@@ -1922,16 +1922,23 @@
 , %22cljs%22
+, %22jsx%22
 %0A    %7D;%0A

Add translation support for .jsx files