/*
******************************************************************************
* Copyright (C) 2003-2012, International Business Machines Corporation and   *
* others. All Rights Reserved.                                               *
******************************************************************************
*/

package com.ibm.icu.impl;

import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.Map;
import java.util.TreeMap;

import com.ibm.icu.impl.locale.AsciiUtil;

/**
 * Utility class to parse and normalize locale ids (including POSIX style)
 */
public final class LocaleIDParser {
    
    /**
     * Char array representing the locale ID.
     */
    private char[] id;
    
    /**
     * Current position in {@link #id} (while parsing).
     */
    private int index;
    
    /**
     * Temporary buffer for parsed sections of data.
     */
    private StringBuilder buffer;
    
    // um, don't handle POSIX ids unless we request it.  why not?  well... because.
    private boolean canonicalize;
    private boolean hadCountry;

    // used when canonicalizing
    Map<String, String> keywords;
    String baseName;

    /**
     * Parsing constants.
     */
    private static final char KEYWORD_SEPARATOR     = '@';
    private static final char HYPHEN                = '-';
    private static final char KEYWORD_ASSIGN        = '=';
    private static final char COMMA                 = ',';
    private static final char ITEM_SEPARATOR        = ';';
    private static final char DOT                   = '.';
    private static final char UNDERSCORE            = '_';

    public LocaleIDParser(String localeID) {
        this(localeID, false);
    }

    public LocaleIDParser(String localeID, boolean canonicalize) {
        id = localeID.toCharArray();
        index = 0;
        buffer = new StringBuilder(id.length + 5);
        this.canonicalize = canonicalize;
    }

    private void reset() {
        index = 0;
        buffer = new StringBuilder(id.length + 5);
    }

    // utilities for working on text in the buffer
    
    /**
     * Append c to the buffer.
     */
    private void append(char c) {
        buffer.append(c);
    }
    
    private void addSeparator() {
        append(UNDERSCORE);
    }

    /**
     * Returns the text in the buffer from start to blen as a String.
     */
    private String getString(int start) {
        return buffer.substring(start);
    }

    /**
     * Set the length of the buffer to pos, then append the string.
     */
    private void set(int pos, String s) {
        buffer.delete(pos, buffer.length());
        buffer.insert(pos, s);
    }

    /**
     * Append the string to the buffer.
     */
    private void append(String s) {
        buffer.append(s);
    }

    // utilities for parsing text out of the id

    /**
     * Character to indicate no more text is available in the id.
     */
    private static final char DONE = '\uffff';

    /**
     * Returns the character at index in the id, and advance index.  The returned character
     * is DONE if index was at the limit of the buffer.  The index is advanced regardless
     * so that decrementing the index will always 'unget' the last character returned.
     */
    private char next() {
        if (index == id.length) {
            index++;
            return DONE;
        }

        return id[index++];
    }

    /**
     * Advance index until the next terminator or id separator, and leave it there.
     */
    private void skipUntilTerminatorOrIDSeparator() {
        while (!isTerminatorOrIDSeparator(next()));
        --index;
    }

    /**
     * Returns true if the character at index in the id is a terminator.
     */
    private boolean atTerminator() {
        return index >= id.length || isTerminator(id[index]);
    }

    /**
     * Returns true if the character is a terminator (keyword separator, dot, or DONE).
     * Dot is a terminator because of the POSIX form, where dot precedes the codepage.
     */
    private boolean isTerminator(char c) {
        // always terminate at DOT, even if not handling POSIX.  It's an error...
        return c == KEYWORD_SEPARATOR || c == DONE || c == DOT;
    }

    /**
     * Returns true if the character is a terminator or id separator.
     */
    private boolean isTerminatorOrIDSeparator(char c) {
        return c == UNDERSCORE || c == HYPHEN || isTerminator(c);
    }

    /**
     * Returns true if the start of the buffer has an experimental or private language
     * prefix, the pattern '[ixIX][-_].' shows the syntax checked.
     */
    private boolean haveExperimentalLanguagePrefix() {
        if (id.length > 2) {
            char c = id[1];
            if (c == HYPHEN || c == UNDERSCORE) {
                c = id[0];
                return c == 'x' || c == 'X' || c == 'i' || c == 'I';
            }
        }
        return false;
    }

    /**
     * Returns true if a value separator occurs at or after index.
     */
    private boolean haveKeywordAssign() {
        // assume it is safe to start from index
        for (int i = index; i < id.length; ++i) {
            if (id[i] == KEYWORD_ASSIGN) {
                return true;
            }
        }
        return false;
    }

    /**
     * Advance index past language, and accumulate normalized language code in buffer.
     * Index must be at 0 when this is called.  Index is left at a terminator or id
     * separator.  Returns the start of the language code in the buffer.
     */
    private int parseLanguage() {
        int startLength = buffer.length();
        
        if (haveExperimentalLanguagePrefix()) {
            append(AsciiUtil.toLower(id[0]));
            append(HYPHEN);
            index = 2;
        }

        char c;
        while(!isTerminatorOrIDSeparator(c = next())) {
            append(AsciiUtil.toLower(c));
        }
        --index; // unget

        if (buffer.length() - startLength == 3) {
            String lang = LocaleIDs.threeToTwoLetterLanguage(getString(0));
            if (lang != null) {
                set(0, lang);
            }
        }

        return 0;
    }

    /**
     * Advance index past language.  Index must be at 0 when this is called.  Index
     * is left at a terminator or id separator.
     */
    private void skipLanguage() {
        if (haveExperimentalLanguagePrefix()) {
            index = 2;
        }
        skipUntilTerminatorOrIDSeparator();
    }

    /**
     * Advance index past script, and accumulate normalized script in buffer.
     * Index must be immediately after the language.
     * If the item at this position is not a script (is not four characters
     * long) leave index and buffer unchanged.  Otherwise index is left at
     * a terminator or id separator.  Returns the start of the script code
     * in the buffer (this may be equal to the buffer length, if there is no
     * script).
     */
    private int parseScript() {
        if (!atTerminator()) {
            int oldIndex = index; // save original index
            ++index;

            int oldBlen = buffer.length(); // get before append hyphen, if we truncate everything is undone
            char c;
            boolean firstPass = true;
            while(!isTerminatorOrIDSeparator(c = next()) && AsciiUtil.isAlpha(c)) {
                if (firstPass) {
                    addSeparator();
                    append(AsciiUtil.toUpper(c));
                    firstPass = false;
                } else {
                    append(AsciiUtil.toLower(c));
                }
            }
            --index; // unget

            /* If it's not exactly 4 characters long, then it's not a script. */
            if (index - oldIndex != 5) { // +1 to account for separator
                index = oldIndex;
                buffer.delete(oldBlen, buffer.length());
            } else {
                oldBlen++; // index past hyphen, for clients who want to extract just the script
            }

            return oldBlen;
        }
        return buffer.length();
    }

    /**
     * Advance index past script.
     * Index must be immediately after the language and IDSeparator.
     * If the item at this position is not a script (is not four characters
     * long) leave index.  Otherwise index is left at a terminator or
     * id separator.
     */
    private void skipScript() {
        if (!atTerminator()) {
            int oldIndex = index;
            ++index;
            
            char c;
            while (!isTerminatorOrIDSeparator(c = next()) && AsciiUtil.isAlpha(c));
            --index;

            if (index - oldIndex != 5) { // +1 to account for separator
                index = oldIndex;
            }
        }
    }

    /**
     * Advance index past country, and accumulate normalized country in buffer.
     * Index must be immediately after the script (if there is one, else language)
     * and IDSeparator.  Return the start of the country code in the buffer.
     */
    private int parseCountry() {
        if (!atTerminator()) {
            int oldIndex = index;
            ++index;

            int oldBlen = buffer.length();
            char c;
            boolean firstPass = true;
            while (!isTerminatorOrIDSeparator(c = next())) {
                if (firstPass) { // first, add hyphen
                    hadCountry = true; // we have a country, let variant parsing know
                    addSeparator();
                    ++oldBlen; // increment past hyphen
                    firstPass = false;
                }
                append(AsciiUtil.toUpper(c));
            }
            --index; // unget

            int charsAppended = buffer.length() - oldBlen;

            if (charsAppended == 0) {
                // Do nothing.
            }
            else if (charsAppended < 2 || charsAppended > 3) {
                // It's not a country, so return index and blen to
                // their previous values.
                index = oldIndex;
                --oldBlen;
                buffer.delete(oldBlen, buffer.length());
                hadCountry = false;
            }
            else if (charsAppended == 3) {
                String region = LocaleIDs.threeToTwoLetterRegion(getString(oldBlen));
                if (region != null) {
                    set(oldBlen, region);
                }
            }

            return oldBlen;
        }

        return buffer.length();
    }

    /**
     * Advance index past country.
     * Index must be immediately after the script (if there is one, else language)
     * and IDSeparator.
     */
    private void skipCountry() {
        if (!atTerminator()) {
            if (id[index] == UNDERSCORE || id[index] == HYPHEN) {
                ++index;
            }
            /*
             * Save the index point after the separator, since the format
             * requires two separators if the country is not present.
             */
            int oldIndex = index;

            skipUntilTerminatorOrIDSeparator();
            int charsSkipped = index - oldIndex;
            if (charsSkipped < 2 || charsSkipped > 3) {
                index = oldIndex;
            }
        }
    }

    /**
     * Advance index past variant, and accumulate normalized variant in buffer.  This ignores
     * the codepage information from POSIX ids.  Index must be immediately after the country
     * or script.  Index is left at the keyword separator or at the end of the text.  Return
     * the start of the variant code in the buffer.
     *
     * In standard form, we can have the following forms:
     * ll__VVVV
     * ll_CC_VVVV
     * ll_Ssss_VVVV
     * ll_Ssss_CC_VVVV
     *
     * This also handles POSIX ids, which can have the following forms (pppp is code page id):
     * ll_CC.pppp          --> ll_CC
     * ll_CC.pppp@VVVV     --> ll_CC_VVVV
     * ll_CC@VVVV          --> ll_CC_VVVV
     *
     * We identify this use of '@' in POSIX ids by looking for an '=' following
     * the '@'.  If there is one, we consider '@' to start a keyword list, instead of
     * being part of a POSIX id.
     *
     * Note:  since it was decided that we want an option to not handle POSIX ids, this
     * becomes a bit more complex.
     */
    private int parseVariant() {
        int oldBlen = buffer.length();

        boolean start = true;
        boolean needSeparator = true;
        boolean skipping = false;
        char c;
        boolean firstPass = true;
        
        while ((c = next()) != DONE) {
            if (c == DOT) {
                start = false;
                skipping = true;
            } else if (c == KEYWORD_SEPARATOR) {
                if (haveKeywordAssign()) {
                    break;
                }
                skipping = false;
                start = false;
                needSeparator = true; // add another underscore if we have more text
            } else if (start) {
                start = false;
                if (c != UNDERSCORE && c != HYPHEN) {
                    index--;
                }
            } else if (!skipping) {
                if (needSeparator) {
                    needSeparator = false;
                    if (firstPass && !hadCountry) { // no country, we'll need two
                        addSeparator();
                        ++oldBlen; // for sure
                    }
                    addSeparator();
                    if (firstPass) { // only for the first separator
                        ++oldBlen;
                        firstPass = false;
                    }
                }
                c = AsciiUtil.toUpper(c);
                if (c == HYPHEN || c == COMMA) {
                    c = UNDERSCORE;
                }
                append(c);
            }
        }
        --index; // unget

        return oldBlen;
    }

    // no need for skipvariant, to get the keywords we'll just scan directly for
    // the keyword separator

    /**
     * Returns the normalized language id, or the empty string.
     */
    public String getLanguage() {
        reset();
        return getString(parseLanguage());
    }

    /**
     * Returns the normalized script id, or the empty string.
     */
    public String getScript() {
        reset();
        skipLanguage();
        return getString(parseScript());
    }

    /**
     * return the normalized country id, or the empty string.
     */
    public String getCountry() {
        reset();
        skipLanguage();
        skipScript();
        return getString(parseCountry());
    }

    /**
     * Returns the normalized variant id, or the empty string.
     */
    public String getVariant() {
        reset();
        skipLanguage();
        skipScript();
        skipCountry();
        return getString(parseVariant());
    }

    /**
     * Returns the language, script, country, and variant as separate strings.
     */
    public String[] getLanguageScriptCountryVariant() {
        reset();
        return new String[] {
                getString(parseLanguage()),
                getString(parseScript()),
                getString(parseCountry()),
                getString(parseVariant())
        };
    }

    public void setBaseName(String baseName) {
        this.baseName = baseName;
    }

    public void parseBaseName() {
        if (baseName != null) {
            set(0, baseName);
        } else {
            reset();
            parseLanguage();
            parseScript();
            parseCountry();
            parseVariant();

            // catch unwanted trailing underscore after country if there was no variant
            int len = buffer.length();
            if (len > 0 && buffer.charAt(len - 1) == UNDERSCORE) {
                buffer.deleteCharAt(len - 1);
            }
        }
    }

    /**
     * Returns the normalized base form of the locale id.  The base
     * form does not include keywords.
     */
    public String getBaseName() {
        if (baseName != null) {
            return baseName;
        }
        parseBaseName();
        return getString(0);
    }

    /**
     * Returns the normalized full form of the locale id.  The full
     * form includes keywords if they are present.
     */
    public String getName() {
        parseBaseName();
        parseKeywords();
        return getString(0);
    }

    // keyword utilities

    /**
     * If we have keywords, advance index to the start of the keywords and return true,
     * otherwise return false.
     */
    private boolean setToKeywordStart() {
        for (int i = index; i < id.length; ++i) {
            if (id[i] == KEYWORD_SEPARATOR) {
                if (canonicalize) {
                    for (int j = ++i; j < id.length; ++j) { // increment i past separator for return
                        if (id[j] == KEYWORD_ASSIGN) {
                            index = i;
                            return true;
                        }
                    }
                } else {
                    if (++i < id.length) {
                        index = i;
                        return true;
                    }
                }
                break;
            }
        }
        return false;
    }

    private static boolean isDoneOrKeywordAssign(char c) {
        return c == DONE || c == KEYWORD_ASSIGN;
    }

    private static boolean isDoneOrItemSeparator(char c) {
        return c == DONE || c == ITEM_SEPARATOR;
    }

    private String getKeyword() {
        int start = index;
        while (!isDoneOrKeywordAssign(next())) {
        }
        --index;
        return AsciiUtil.toLowerString(new String(id, start, index-start).trim());
    }

    private String getValue() {
        int start = index;
        while (!isDoneOrItemSeparator(next())) {
        }
        --index;
        return new String(id, start, index-start).trim(); // leave case alone
    }

    private Comparator<String> getKeyComparator() {
        final Comparator<String> comp = new Comparator<String>() {
            public int compare(String lhs, String rhs) {
                return lhs.compareTo(rhs);
            }
        };
        return comp;
    }

    /**
     * Returns a map of the keywords and values, or null if there are none.
     */
    public Map<String, String> getKeywordMap() {
        if (keywords == null) {
            TreeMap<String, String> m = null;
            if (setToKeywordStart()) {
                // trim spaces and convert to lower case, both keywords and values.
                do {
                    String key = getKeyword();
                    if (key.length() == 0) {
                        break;
                    }
                    char c = next();
                    if (c != KEYWORD_ASSIGN) {
                        // throw new IllegalArgumentException("key '" + key + "' missing a value.");
                        if (c == DONE) {
                            break;
                        } else {
                            continue;
                        }
                    }
                    String value = getValue();
                    if (value.length() == 0) {
                        // throw new IllegalArgumentException("key '" + key + "' missing a value.");
                        continue;
                    }
                    if (m == null) {
                        m = new TreeMap<String, String>(getKeyComparator());
                    } else if (m.containsKey(key)) {
                        // throw new IllegalArgumentException("key '" + key + "' already has a value.");
                        continue;
                    }
                    m.put(key, value);
                } while (next() == ITEM_SEPARATOR);
            }
            keywords = m != null ? m : Collections.<String, String>emptyMap();
        }

        return keywords;
    }


    /**
     * Parse the keywords and return start of the string in the buffer.
     */
    private int parseKeywords() {
        int oldBlen = buffer.length();
        Map<String, String> m = getKeywordMap();
        if (!m.isEmpty()) {
            boolean first = true;
            for (Map.Entry<String, String> e : m.entrySet()) {
                append(first ? KEYWORD_SEPARATOR : ITEM_SEPARATOR);
                first = false;
                append(e.getKey());
                append(KEYWORD_ASSIGN);
                append(e.getValue());
            }
            if (first == false) {
                ++oldBlen;
            }
        }
        return oldBlen;
    }

    /**
     * Returns an iterator over the keywords, or null if we have an empty map.
     */
    public Iterator<String> getKeywords() {
        Map<String, String> m = getKeywordMap();
        return m.isEmpty() ? null : m.keySet().iterator();
    }

    /**
     * Returns the value for the named keyword, or null if the keyword is not
     * present.
     */
    public String getKeywordValue(String keywordName) {
        Map<String, String> m = getKeywordMap();
        return m.isEmpty() ? null : m.get(AsciiUtil.toLowerString(keywordName.trim()));
    }

    /**
     * Set the keyword value only if it is not already set to something else.
     */
    public void defaultKeywordValue(String keywordName, String value) {
        setKeywordValue(keywordName, value, false);
    }

    /**
     * Set the value for the named keyword, or unset it if value is null.  If
     * keywordName itself is null, unset all keywords.  If keywordName is not null,
     * value must not be null.
     */
    public void setKeywordValue(String keywordName, String value) {
        setKeywordValue(keywordName, value, true);
    }

    /**
     * Set the value for the named keyword, or unset it if value is null.  If
     * keywordName itself is null, unset all keywords.  If keywordName is not null,
     * value must not be null.  If reset is true, ignore any previous value for
     * the keyword, otherwise do not change the keyword (including removal of
     * one or all keywords).
     */
    private void setKeywordValue(String keywordName, String value, boolean reset) {
        if (keywordName == null) {
            if (reset) {
                // force new map, ignore value
                keywords = Collections.<String, String>emptyMap();
            }
        } else {
            keywordName = AsciiUtil.toLowerString(keywordName.trim());
            if (keywordName.length() == 0) {
                throw new IllegalArgumentException("keyword must not be empty");
            }
            if (value != null) {
                value = value.trim();
                if (value.length() == 0) {
                    throw new IllegalArgumentException("value must not be empty");
                }
            }
            Map<String, String> m = getKeywordMap();
            if (m.isEmpty()) { // it is EMPTY_MAP
                if (value != null) {
                    // force new map
                    keywords = new TreeMap<String, String>(getKeyComparator());
                    keywords.put(keywordName, value.trim());
                }
            } else {
                if (reset || !m.containsKey(keywordName)) {
                    if (value != null) {
                        m.put(keywordName, value);
                    } else {
                        m.remove(keywordName);
                        if (m.isEmpty()) {
                            // force new map
                            keywords = Collections.<String, String>emptyMap();
                        }
                    }
                }
            }
        }
    }
}
