// Copyright 2015 The Vanadium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package io.v.v23.i18n;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import io.v.v23.verror.VException;

/**
 * Catalog maps language names and message identifiers to message format strings.  The intent is
 * to provide a primitive form of String.format() in a way where the format string can depend upon
 * the language.
 * <p>
 * Languages are specified in the IETF language tag format.  Language tags can be obtained easily
 * by calling the {@link java.util.Locale#toLanguageTag} method.  Empty string indicates that the
 * default locale's language should be used.
 * <p>
 * Message identifier is a string that identifies a set of message format strings that have the
 * same meaning, but may be available in multiple languages.
 * <p>
 * A message format string is a string containing substrings of the form {@code {<number>}}
 * which are replaced by the corresponding position parameter (numbered from 1), or
 * {@code {_}}, which is replaced by all otherwise unused parameters.  If a substring is of the
 * form {@code {:<number>}}, {@code {<number>:}}, {@code {:<number>:}}, {@code {:_}}, {@code {_:}},
 * or {@code {:_:}} and the corresponding parameters are not the empty string, the parameter is
 * preceded by {@code ": "} or followed by {@code ":"}  or both, respectively.  For example, if the
 * format:
 * <p><blockquote><pre>
 * {3:} foo {2} bar{:_} ({3})
 * </pre></blockquote><p>
 * is used with arguments:
 * <p><blockquote><pre>
 * "1st", "2nd", "3rd", "4th"
 * </pre></blockquote><p>
 * it yields:
 * <p><blockquote><pre>
 * 3rd: foo 2nd bar: 1st 4th (3rd)
 * </pre></blockquote><p>
 *
 * The positional parameters may have any type and are printed in their default formatting.
 * If a particular formatting is desired, the parameter should be converted to a string first.
 * In principle, the default formating for a parameter may depend on a language tag.
 *
 * A typical usage pattern of this class goes like:
 * <p><blockquote><pre>
 * Catalog cat = Language.getDefaultCatalog();
 * String output = cat.format(language, msgID, "1st", "2nd", "3rd", "4th");
 * </pre></blockquote><p>
 */
public class Catalog {
    private static native String nativeFormatParams(String format, String[] params)
            throws VException;

    /**
     * Returns a copy of format with instances of {@code {1}}, {@code {2}}, etc replaced by the
     * default string representation of {@code params[0]}, {@code params[1]}, etc.  The last
     * instance of the string {@code {_}} is replaced with a space-separated list of positional
     * parameters unused by other {@code {...}} sequences.  Missing parameters are replaced
     * with {@code "?"}.
     *
     * @param  format message format
     * @param  params message parameters
     * @return        the result of applying the parameters to the given format
     */
    public static String formatParams(String format, Object... params) {
        try {
            return nativeFormatParams(format, convertParamsToStr(params));
        } catch (VException e) {
            throw new RuntimeException("Couldn't format params.", e);
        }
    }

    private static String[] convertParamsToStr(Object... params) {
        String[] ret = new String[params.length];
        for (int i = 0; i < params.length; ++i) {
            ret[i] = "" + params[i];
        }
        return ret;
    }

    // language -> (msgID -> format)
    private final Map<String, Map<String, String>> formats;
    private final ReadWriteLock lock;

    /**
     * Creates a new empty {@link Catalog}.
     */
    public Catalog() {
        this.formats = new HashMap<String, Map<String, String>>();
        this.lock = new ReentrantReadWriteLock();
    }

    /**
     * Returns the format corresponding to a given language and message identifier.
     * If no such message is known, any message for a base language is retrieved.
     * If no such message exists, empty string is returned.
     *
     * @param  language language that is looked up
     * @param  msgID    message identifier that is looked up
     * @return          a format corresponding to the given language and message identifier
     */
    public String lookup(String language, String msgID) {
        this.lock.readLock().lock();
        String fmt = lookupUnlocked(language, msgID);
        if (fmt.isEmpty()) {
            fmt = lookupUnlocked(Language.baseLanguage(language), msgID);
        }
        this.lock.readLock().unlock();
        return fmt;
    }

    private String lookupUnlocked(String language, String msgID) {
        Map<String, String> msgFmtMap = this.formats.get(language);
        if (msgFmtMap == null) {
            return "";
        }
        String fmt = msgFmtMap.get(msgID);
        return fmt == null ? "" : fmt;
    }

    /**
     * Finds the format corresponding to a given language and message identifier and then applies
     * {@link #formatParams formatParams} to it with the given params.  If the format lookup fails,
     * the result is the text of the message followed by a colon and then the parameters.
     *
     * @param  language language used for the format lookup
     * @param  msgID    message identifier used for the format lookup
     * @param  params   message parameters
     * @return          the result of applying the parameters to the looked-up format
     */
    public String format(String language, String msgID, Object... params) {
        String formatStr = lookup(language, msgID);
        if (formatStr.isEmpty()) {
            formatStr = msgID;
            if (params.length > 0) {
                formatStr += "{:_}";
            }
        }
        return formatParams(formatStr, params);
    }

    /**
     * Sets the format corresponding to the given language and message identifier.  If the format
     * string is empty, the corresponding entry is removed.  Any previous format string is returned.
     *
     * @param  language  language to be associated with the format
     * @param  msgID     message identifier to be associated with the format
     * @param  newFormat format assigned to the given language and message identifier
     * @return           previous format associated with the given language and message identifier
     */
    public String set(String language, String msgID, String newFormat) {
        this.lock.writeLock().lock();
        String oldFormat = setUnlocked(language, msgID, newFormat);
        this.lock.writeLock().unlock();
        return oldFormat;
    }

    /**
     * Just like {@link #set set} but additionaly sets the format for the base language if not
     * already set.  Note that if the new format is empty, the entry for the base language WILL NOT
     * be removed.
     *
     * @param  language  language to be associated with the format
     * @param  msgID     message identifier to be associated with the format
     * @param  newFormat format assigned to the given language and message identifier
     * @return           previous format associated with the given language and message identifier
     */
    public String setWithBase(String language, String msgID, String newFormat) {
        this.lock.writeLock().lock();
        String oldFormat = setUnlocked(language, msgID, newFormat);
        String baseLang = Language.baseLanguage(language);
        String baseFmt = lookupUnlocked(baseLang, msgID);
        if (baseFmt.isEmpty() && !newFormat.isEmpty() && !baseLang.equals(language)) {
            setUnlocked(baseLang, msgID, newFormat);
        }
        this.lock.writeLock().unlock();
        return oldFormat;
    }

    private String setUnlocked(String language, String msgID, String newFormat) {
        Map<String, String> msgFmtMap = this.formats.get(language);
        if (msgFmtMap == null) {
            msgFmtMap = new HashMap<String, String>();
            this.formats.put(language, msgFmtMap);
        }
        String oldFormat = msgFmtMap.get(msgID);
        if (newFormat != null && !newFormat.isEmpty()) {
            msgFmtMap.put(msgID, newFormat);
        } else {
            msgFmtMap.remove(msgID);
            if (msgFmtMap.isEmpty()) {
                this.formats.remove(language);
            }
        }
        return oldFormat == null ? "" : oldFormat;
    }

    /**
     * Merges the data in the lines from the provided input stream into the catalog.
     * Each line from the input stream is expected to be in the following format:
     * <p><blockquote><pre>
     *      {@literal <language> <message ID> "<escaped format string>"}
     * </pre></blockquote><p>
     * If a line starts with a {@code #} or cannot be parsed, the line is ignored.
     *
     * @param  in          input stream containing lines in the above format
     * @throws IOException if there was an error reading the input stream
     */
    public void merge(InputStream in) throws IOException {
        BufferedReader reader = new BufferedReader(new InputStreamReader(in));
        String line = null;
        Pattern pattern =
                Pattern.compile("^\\s*([^\\s\"]+)\\s+([^\\s\"]+)\\s+\"((?:[^\"]|\\\")*)\".*$");
        while ((line = reader.readLine()) != null) {
            Matcher matcher = pattern.matcher(line);
            if (matcher.matches() &&
                matcher.groupCount() == 3 && !matcher.group(1).startsWith("#")) {
                String language = matcher.group(1);
                String msgID = matcher.group(2);
                String format = matcher.group(3);
                set(language, msgID, format);
            }
        }
        reader.close();
    }

    /**
     * Emits the contents of the catalog into the provided output stream, in the format
     * expected by {@link #merge merge}.
     *
     * @param  out         output stream into which the catalog is emitted
     * @throws IOException if there was an error writing to the output stream
     */
    public void output(OutputStream out) throws IOException {
        BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(out));
        this.lock.readLock().lock();
        for (Map.Entry<String, Map<String, String>> entry : this.formats.entrySet()) {
            String language = entry.getKey();
            for (Map.Entry<String, String> idFmt : entry.getValue().entrySet()) {
                String msgID = idFmt.getKey();
                String format = idFmt.getValue();
                writer.write(String.format("%s %s \"%s\"\n", language, msgID, format));
            }
        }
        this.lock.readLock().unlock();
        writer.close();
    }
}