/*
 *******************************************************************************
 * Copyright (C) 2009, International Business Machines Corporation and         *
 * others. All Rights Reserved.                                                *
 *******************************************************************************
 */
package com.ibm.icu.impl.locale;

import java.util.List;
import java.util.Set;
import java.util.SortedMap;
import java.util.TreeMap;

import com.ibm.icu.impl.locale.LanguageTag.ParseStatus;

public final class InternalLocaleBuilder {

    private String _language = "";
    private String _script = "";
    private String _region = "";
    private String _variant = "";
    private SortedMap<Character, Extension> _extMap;

    private final boolean _lenientVariant;

    private static final String LOCALESEP = "_";

    public InternalLocaleBuilder() {
        this(false);
    }

    public InternalLocaleBuilder(boolean lenientVariant) {
        _lenientVariant = lenientVariant;
    }

    public boolean isLenientVariant() {
        return _lenientVariant;
    }

    public InternalLocaleBuilder setLanguage(String language) throws LocaleSyntaxException {
        String newval = "";
        if (language.length() > 0) {
            if (!LanguageTag.isLanguage(language)) {
                throw new LocaleSyntaxException("Ill-formed language: " + language, 0);
            }
            newval = LanguageTag.canonicalizeLanguage(language);
        }
        _language = newval;
        return this;
    }

    public InternalLocaleBuilder setScript(String script) throws LocaleSyntaxException {
        String newval = "";
        if (script.length() > 0) {
            if (!LanguageTag.isScript(script)) {
                throw new LocaleSyntaxException("Ill-formed script: " + script, 0);
            }
            newval = LanguageTag.canonicalizeScript(script);
        }
        _script = newval;
        return this;
    }

    public InternalLocaleBuilder setRegion(String region) throws LocaleSyntaxException {
        String newval = "";
        if (region.length() > 0) {
            if (!LanguageTag.isRegion(region)) {
                throw new LocaleSyntaxException("Ill-formed region: " + region);
            }
            newval = LanguageTag.canonicalizeRegion(region);
        }
        _region = newval;
        return this;
    }

    public InternalLocaleBuilder setVariant(String variant) throws LocaleSyntaxException {
        String newval = "";
        if (variant.length() > 0) {
            if (_lenientVariant) {
                newval = variant;
            } else {
                newval = processVariant(variant);
            }
        }
        _variant = newval;
        return this;
    }

    public InternalLocaleBuilder setUnicodeLocaleExtension(String key, String type) throws LocaleSyntaxException {
        if (key.length() == 0) {
            throw new LocaleSyntaxException("Empty Unicode locale extension key");
        }
        if (!UnicodeLocaleExtension.isKey(key)) {
            throw new LocaleSyntaxException("Ill-formed Unicode locale extension key: " + key, 0);
        }

        key = UnicodeLocaleExtension.canonicalizeKey(key);

        UnicodeLocaleExtension ulext = null;
        if (_extMap != null) {
            ulext = (UnicodeLocaleExtension)_extMap.get(Character.valueOf(UnicodeLocaleExtension.SINGLETON));
        }

        if (type.length() == 0) {
            if (ulext != null) {
                ulext.remove(key);
                if (ulext.isEmpty()) {
                    _extMap.remove(Character.valueOf(UnicodeLocaleExtension.SINGLETON));
                }
            }
        } else {
            StringBuilder buf = new StringBuilder();
            StringTokenIterator sti = new StringTokenIterator(type, LanguageTag.SEP);
            for (String subtag = sti.first(); !sti.isDone(); subtag = sti.next()) {
                if (!UnicodeLocaleExtension.isTypeSubtag(subtag)) {
                    throw new LocaleSyntaxException("Ill-formed Unicode locale extension type: " + type, sti.currentStart());
                }
                if (buf.length() > 0) {
                    buf.append(LanguageTag.SEP);
                }
                buf.append(UnicodeLocaleExtension.canonicalizeTypeSubtag(subtag));
            }
            if (ulext == null) {
                SortedMap<String, String> ktmap = new TreeMap<String, String>();
                ktmap.put(key, buf.toString());
                ulext = new UnicodeLocaleExtension(ktmap);
                if (_extMap == null) {
                    _extMap = new TreeMap<Character, Extension>();
                }
                _extMap.put(Character.valueOf(UnicodeLocaleExtension.SINGLETON), ulext);
            } else {
                ulext.put(key, buf.toString());
            }
        }

        return this;
    }

    public InternalLocaleBuilder setExtension(char singleton, String value) throws LocaleSyntaxException {
        String strSingleton = String.valueOf(singleton);
        if (!LanguageTag.isExtensionSingleton(strSingleton) && !LanguageTag.isPrivateuseSingleton(strSingleton)) {
            throw new LocaleSyntaxException("Ill-formed extension key: " + singleton);
        }

        strSingleton = LanguageTag.canonicalizeExtensionSingleton(strSingleton);
        Character key = Character.valueOf(strSingleton.charAt(0));

        if (value.length() == 0) {
            if (_extMap != null) {
                _extMap.remove(key);
            }
        } else {
            StringTokenIterator sti = new StringTokenIterator(value, LanguageTag.SEP);
            ParseStatus sts = new ParseStatus();

            Extension ext = Extension.create(key.charValue(), sti, sts);
            if (sts.isError()) {
                throw new LocaleSyntaxException(sts.errorMsg, sts.errorIndex);
            }
            if (sts.parseLength != value.length() || ext == null) {
                throw new LocaleSyntaxException("Ill-formed extension value: " + value, sti.currentStart());
            }
            if (_extMap == null) {
                _extMap = new TreeMap<Character, Extension>();
            }
            _extMap.put(key, ext);
        }
        return this;
    }

    public InternalLocaleBuilder setLocale(BaseLocale base, LocaleExtensions extensions) throws LocaleSyntaxException {
        String language = base.getLanguage();
        String script = base.getScript();
        String region = base.getRegion();
        String variant = base.getVariant();

        // Validate base locale fields before updating internal state.
        // LocaleExtensions always store validated/canonicalized values,
        // so no checks are necessary.
        if (language.length() > 0) {
            if (!LanguageTag.isLanguage(language)) {
                throw new LocaleSyntaxException("Ill-formed language: " + language);
            }
            language = LanguageTag.canonicalizeLanguage(language);
        }
        if (script.length() > 0) {
            if (!LanguageTag.isScript(script)) {
                throw new LocaleSyntaxException("Ill-formed script: " + script);
            }
            script = LanguageTag.canonicalizeScript(script);
        }
        if (region.length() > 0) {
            if (!LanguageTag.isRegion(region)) {
                throw new LocaleSyntaxException("Ill-formed region: " + region);
            }
            region = LanguageTag.canonicalizeRegion(region);
        }
        if (_lenientVariant) {
            // In lenient variant mode, parse special private use value
            // reserved for Java Locale.
            String privuse = extensions.getExtensionValue(Character.valueOf(LanguageTag.PRIVATEUSE.charAt(0)));
            if (privuse != null) {
                variant = LanguageTag.getJavaCompatibleVariant(variant, privuse);
            }
        } else {
            if (variant.length() > 0) {
                variant = processVariant(variant);
            }
        }

        // update builder's internal fields
        _language = language;
        _script = script;
        _region = region;
        _variant = variant;

        // empty extensions
        if (_extMap == null) {
            _extMap = new TreeMap<Character, Extension>();
        } else {
            _extMap.clear();
        }

        Set<Character> extKeys = extensions.getKeys();
        for (Character key : extKeys) {
            Extension ext = extensions.getExtension(key);
            if (_lenientVariant && (ext instanceof PrivateuseExtension)) {
                String modPrivuse = LanguageTag.getJavaCompatiblePrivateuse(ext.getValue());
                if (!modPrivuse.equals(ext.getValue())) {
                    ext = new PrivateuseExtension(modPrivuse);
                }
            }
            _extMap.put(key, ext);
        }

        return this;
    }

    public InternalLocaleBuilder clear() {
        _language = "";
        _script = "";
        _region = "";
        _variant = "";
        removeLocaleExtensions();
        return this;
    }

    public InternalLocaleBuilder removeLocaleExtensions() {
        if (_extMap != null) {
            _extMap.clear();
        }
        return this;
    }

    public BaseLocale getBaseLocale() {
        return BaseLocale.getInstance(_language, _script, _region, _variant);
    }

    public LocaleExtensions getLocaleExtensions() {
        if (_extMap != null && _extMap.size() > 0) {
            return LocaleExtensions.getInstance(_extMap);
        }
        return LocaleExtensions.EMPTY_EXTENSIONS;
    }

    private String processVariant(String variant) throws LocaleSyntaxException {
        StringTokenIterator sti = new StringTokenIterator(variant, LOCALESEP);
        ParseStatus sts = new ParseStatus();

        List<String> variants = LanguageTag.DEFAULT_PARSER.parseVariants(sti, sts);
        if (sts.parseLength != variant.length()) {
            throw new LocaleSyntaxException("Ill-formed variant: " + variant, sti.currentStart());
        }

        StringBuilder buf = new StringBuilder();
        for (String var : variants) {
            if (buf.length() != 0) {
                buf.append(LOCALESEP);
            }
            buf.append(var);
        }
        return buf.toString();
    }
}
