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

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;

import com.ibm.icu.impl.Utility;

public final class InternalLocaleBuilder {

    public static final char PRIVATEUSEKEY = 'x';

    private String _language = "";
    private String _script = "";
    private String _region = "";
    private String _variant = "";

    private FieldHandler _handler = FieldHandler.DEFAULT;

//    private HashMap<Character, String> _extMap;
    private HashMap _extMap;
//    private HashMap<String, String> _kwdMap;
    private HashMap _kwdMap;

    private static final char LDMLSINGLETON = 'u';

    private static final String LANGTAGSEP = "-";
    private static final String LOCALESEP = "_";

    private static final int DEFAULTMAPCAPACITY = 4;

    public InternalLocaleBuilder() {
    }

    public InternalLocaleBuilder(FieldHandler handler) {
        _handler = handler;
    }

    public InternalLocaleBuilder setLanguage(String language) throws LocaleSyntaxException {
        String newval = "";
        if (language.length() > 0) {
            newval = _handler.process(FieldType.LANGUAGE, language);
            if (newval == null) {
                throw new LocaleSyntaxException("Ill-formed language: " + language);
            }
        }
        _language = newval;
        return this;
    }

    public InternalLocaleBuilder setScript(String script) throws LocaleSyntaxException {
        String newval = "";
        if (script.length() > 0) {
            newval = _handler.process(FieldType.SCRIPT, script);
            if (newval == null) {
                throw new LocaleSyntaxException("Ill-formed script: " + script);
            }
        }
        _script = newval;
        return this;
    }

    public InternalLocaleBuilder setRegion(String region) throws LocaleSyntaxException {
        String newval = "";
        if (region.length() > 0) {
            newval = _handler.process(FieldType.REGION, region);
            if (newval == null) {
                throw new LocaleSyntaxException("Ill-formed region: " + region);
            }
        }
        _region = newval;
        return this;
    }

    public InternalLocaleBuilder setVariant(String variant) throws LocaleSyntaxException {
        String newval = "";
        if (variant.length() > 0) {
            newval = _handler.process(FieldType.VARIANT, variant);
            if (newval == null) {
                throw new LocaleSyntaxException("Ill-formed variant: " + variant);
            }
        }
        _variant = newval;
        return this;
    }

    public InternalLocaleBuilder setLDMLExtensionValue(String key, String type) throws LocaleSyntaxException {
        if (key.length() == 0) {
            throw new LocaleSyntaxException("Empty LDML extension key");
        }
        String kwdkey = _handler.process(FieldType.LDMLKEY, key);
        if (kwdkey == null) {
            throw new LocaleSyntaxException("Ill-formed LDML extension key: " + key);
        }

        if (type.length() == 0) {
            if (_kwdMap != null) {
                _kwdMap.remove(kwdkey);
            }
        } else {
            String kwdtype = _handler.process(FieldType.LDMLTYPE, type);
            if (kwdtype == null) {
                throw new LocaleSyntaxException("Ill-formed LDML extension value: " + type);
            }
            if (_kwdMap == null) {
//                _kwdMap = new HashMap<String, String>(DEFAULTMAPCAPACITY);
                _kwdMap = new HashMap(DEFAULTMAPCAPACITY);
            }
            _kwdMap.put(kwdkey, kwdtype);
        }

        return this;
    }

    public InternalLocaleBuilder setExtension(char singleton, String value) throws LocaleSyntaxException {
        if (!LocaleExtensions.isValidExtensionKey(singleton)) {
            throw new LocaleSyntaxException("Ill-formed extension key: " + singleton);
        }

        // singleton char to lower case
        singleton = AsciiUtil.toLower(singleton);

        if (singleton == LDMLSINGLETON) {
            // 'u' extension reserved for locale keywords
            if (_kwdMap != null) {
                // blow out the keywords currently set
                _kwdMap.clear();
            }
            // parse locale keyword extension subtags
//            String[] kwdtags = (value.replaceAll(LOCALESEP, LANGTAGSEP)).split(LANGTAGSEP);
            String[] kwdtags = Utility.split(Utility.replaceAll(value, LOCALESEP, LANGTAGSEP), '-');
            if ((kwdtags.length % 2) != 0) {
                // number of keyword subtags must be even number
                throw new LocaleSyntaxException("Ill-formed LDML extension key/value pairs: " + value);
            }
            int idx = 0;
            while (idx < kwdtags.length) {
                String kwdkey = _handler.process(FieldType.LDMLKEY, kwdtags[idx++]);
                String kwdtype = _handler.process(FieldType.LDMLTYPE, kwdtags[idx++]);
                if (kwdkey == null || kwdkey.length() == 0
                        || kwdtype == null || kwdtype.length() == 0) {
                    throw new LocaleSyntaxException("Ill-formed LDML extension key/value pairs: " + value);
                }
                if (_kwdMap == null) {
//                    _kwdMap = new HashMap<String, String>(kwdtags.length / 2);
                    _kwdMap = new HashMap(kwdtags.length / 2);
                }
                _kwdMap.put(kwdkey, kwdtype);
            }
        } else {
            // other extensions including privateuse
            if (value.length() == 0) {
                if (_extMap != null) {
//                    _extMap.remove(Character.valueOf(singleton));
                    _extMap.remove(new Character(singleton));
                }
            } else {
//                FieldType ftype = (singleton == PRIVATEUSEKEY) ? FieldType.PRIVATEUSE : FieldType.EXTENSION;
                int ftype = (singleton == PRIVATEUSEKEY) ? FieldType.PRIVATEUSE : FieldType.EXTENSION;
                String extval = _handler.process(ftype, value);
                if (extval == null) {
                    throw new LocaleSyntaxException("Ill-formed LDML extension value: " + value);
                }
                if (_extMap == null) {
//                    _extMap = new HashMap<Character, String>(DEFAULTMAPCAPACITY);
                    _extMap = new HashMap(DEFAULTMAPCAPACITY);
                }
//                _extMap.put(Character.valueOf(singleton), extval);
                _extMap.put(new Character(singleton), extval);
            }
        }
        return this;
    }

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

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

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

    public LocaleExtensions getLocaleExtensions() {
//        TreeMap<Character, String> extMap = null;
        TreeMap extMap = null;
//        TreeMap<String, String> kwdMap = null;
        TreeMap kwdMap = null;

        // process keywords
        if (_kwdMap != null && _kwdMap.size() > 0) {
//            Set<Map.Entry<String, String>> kwds = _kwdMap.entrySet();
//            for (Map.Entry<String, String> kwd : kwds) {
//                String key = kwd.getKey();
//                String type = kwd.getValue();
//                if (kwdMap == null) {
//                    kwdMap = new TreeMap<String, String>();
//                }
//                kwdMap.put(key.intern(), type.intern());
//            }
            Set kwds = _kwdMap.entrySet();
            Iterator itr = kwds.iterator();
            while (itr.hasNext()) {
                Map.Entry kwd = (Map.Entry)itr.next();
                String key = (String)kwd.getKey();
                String type = (String)kwd.getValue();
                if (kwdMap == null) {
                    kwdMap = new TreeMap();
                }
                kwdMap.put(key.intern(), type.intern());
            }
        }

        // process extensions and privateuse
        if (_extMap != null) {
//            Set<Map.Entry<Character, String>> exts = _extMap.entrySet();
//            for (Map.Entry<Character, String> ext : exts) {
//                Character key = ext.getKey();
//                String value = ext.getValue();
//                if (extMap == null) {
//                    extMap = new TreeMap<Character, String>();
//                }
//                extMap.put(key, value.intern());
//            }
            Set exts = _extMap.entrySet();
            Iterator itr = exts.iterator();
            while (itr.hasNext()) {
                Map.Entry ext = (Map.Entry)itr.next();
                Character key = (Character)ext.getKey();
                String value = (String)ext.getValue();
                if (extMap == null) {
                    extMap = new TreeMap();
                }
                extMap.put(key, value.intern());
            }
        }

        // set canonical locale keyword extension string to the extension map
        if (kwdMap != null) {
//            StringBuilder buf = new StringBuilder();
            StringBuffer buf = new StringBuffer();
            LocaleExtensions.keywordsToString(kwdMap, buf);
            if (extMap == null) {
//                extMap = new TreeMap<Character, String>();
                extMap = new TreeMap();
            }
//            extMap.put(Character.valueOf(LDMLSINGLETON), buf.toString().intern());
            extMap.put(new Character(LDMLSINGLETON), buf.toString().intern());
        }

        return LocaleExtensions.getInstance(extMap, kwdMap);
    }

//    protected enum FieldType {
//        LANGUAGE,
//        SCRIPT,
//        REGION,
//        VARIANT,
//        LDMLKEY,
//        LDMLTYPE,
//        EXTENSION,
//        PRIVATEUSE
//    }

    private static class FieldType {
        public static final int LANGUAGE = 0;
        public static final int SCRIPT = 1;
        public static final int REGION = 2;
        public static final int VARIANT = 3;
        public static final int LDMLKEY = 4;
        public static final int LDMLTYPE = 5;
        public static final int EXTENSION = 6;
        public static final int PRIVATEUSE = 7;
    }

    public static class FieldHandler {
        public static FieldHandler DEFAULT = new FieldHandler();

        protected FieldHandler() {
        }

//        public String process(FieldType type, String value) {
        public String process(int type, String value) {
            value = map(type, value);
            if (value.length() > 0 && !validate(type, value)) {
                return null;
            }
            return value;
        }

//        protected String map(FieldType type, String value) {
        protected String map(int type, String value) {
            switch (type) {
            case FieldType.LANGUAGE:
                value = AsciiUtil.toLowerString(value);
                break;
            case FieldType.SCRIPT:
                if (value.length() > 0) {
//                    StringBuilder buf = new StringBuilder();
                    StringBuffer buf = new StringBuffer();
                    buf.append(AsciiUtil.toUpper(value.charAt(0)));
                    for (int i = 1; i < value.length(); i++) {
                        buf.append(AsciiUtil.toLower(value.charAt(i)));
                    }
                    value = buf.toString();
                }
                break;
            case FieldType.REGION:
                value = AsciiUtil.toUpperString(value);
                break;
            case FieldType.VARIANT:
                // Java variant is case sensitive - so no case mapping here
//                value = value.replaceAll(LANGTAGSEP, LOCALESEP);
                value = Utility.replaceAll(value, LANGTAGSEP, LOCALESEP);
                break;
            case FieldType.LDMLKEY:
            case FieldType.LDMLTYPE:
            case FieldType.EXTENSION:
            case FieldType.PRIVATEUSE:
//                value = AsciiUtil.toLowerString(value).replaceAll(LOCALESEP, LANGTAGSEP);
                value = Utility.replaceAll(AsciiUtil.toLowerString(value), LOCALESEP, LANGTAGSEP);
                break;
            }
            return value;
        }

//        protected boolean validate(FieldType type, String value) {
        protected boolean validate(int type, String value) {
            boolean isValid = false;
            String[] subtags;

            switch (type) {
            case FieldType.LANGUAGE:
                isValid = LanguageTag.isLanguageSubtag(value);
                break;
            case FieldType.SCRIPT:
                isValid = LanguageTag.isScriptSubtag(value);
                break;
            case FieldType.REGION:
                isValid = LanguageTag.isRegionSubtag(value);
                break;
            case FieldType.VARIANT:
                // variant field could have multiple subtags
//                subtags = value.split(LOCALESEP);
                subtags = Utility.split(value, '_');
//                for (String subtag : subtags) {
                for (int i = 0; i < subtags.length; i++) {
                    String subtag = subtags[i];
                    isValid = LanguageTag.isVariantSubtag(subtag);
                    if (!isValid) {
                        break;
                    }
                }
                break;
            case FieldType.LDMLKEY:
                isValid = LocaleExtensions.isValidLDMLKey(value);
                break;
            case FieldType.LDMLTYPE:
                isValid = LocaleExtensions.isValidLDMLType(value);
                break;
            case FieldType.EXTENSION:
//                subtags = value.split(LANGTAGSEP);
                subtags = Utility.split(value, '-');
//              for (String subtag : subtags) {
                for (int i = 0; i < subtags.length; i++) {
                    String subtag = subtags[i];
                    isValid = LanguageTag.isExtensionSubtag(subtag);
                    if (!isValid) {
                        break;
                    }
                }
                break;
            case FieldType.PRIVATEUSE:
//                subtags = value.split(LANGTAGSEP);
                subtags = Utility.split(value, '-');
//              for (String subtag : subtags) {
                for (int i = 0; i < subtags.length; i++) {
                    String subtag = subtags[i];
                    isValid = LanguageTag.isPrivateuseValueSubtag(subtag);
                    if (!isValid) {
                        break;
                    }
                }
                break;
            }
            return isValid;
        }
    }
}
