/* UtilLib - Copyright (c) 2014-2018 Vincent Calame - Exemole
 * Logiciel libre donné sous triple licence :
 * 1) selon les termes de la CeCILL V2
 * 2) selon les termes de l’EUPL V.1.1
 * 3) selon les termes de la GNU GPLv3
 * Voir le fichier licences.txt
 */


package net.mapeadores.util.localisation;

import java.util.AbstractList;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Set;


/**
 *
 * @author Vincent Calame
 */
public class ListLangContextBuilder {

    private final List<ListLangContext.Unit> unitList = new ArrayList<ListLangContext.Unit>();
    private final Set<Lang> existingLang = new HashSet<Lang>();

    public ListLangContextBuilder() {

    }

    public void addLang(Lang lang) {
        if (lang == null) {
            throw new NullPointerException("lang is null");
        }
        if (!existingLang.contains(lang)) {
            existingLang.add(lang);
            unitList.add(new InternalUnit(lang, lang.toLocale()));
        }
    }

    public void addLang(Lang lang, Locale formatLocale) {
        if (lang == null) {
            throw new NullPointerException("lang is null");
        }
        if (formatLocale == null) {
            throw new NullPointerException("formatLocale is null");
        }
        if (!existingLang.contains(lang)) {
            existingLang.add(lang);
            unitList.add(new InternalUnit(lang, formatLocale));
        }
    }

    public void addLangs(Langs langs) {
        for (Lang lang : langs) {
            addLang(lang);
        }
    }

    public ListLangContext toListLangContext() {
        int size = unitList.size();
        if (size == 0) {
            throw new IllegalStateException("ListLangContext is empty");
        }
        ListLangContext.Unit[] unitArray = unitList.toArray(new ListLangContext.Unit[size]);
        return new InternalListLangContext(unitArray);
    }

    public static ListLangContext build(Lang lang) {
        if (lang == null) {
            throw new NullPointerException("lang is null");
        }
        ListLangContextBuilder builder = new ListLangContextBuilder();
        builder.addLang(lang);
        return builder.toListLangContext();
    }

    public static ListLangContext build(Lang[] langArray) {
        int length = langArray.length;
        if (length == 0) {
            throw new IllegalArgumentException("langIntegerArray.length == 0");
        }
        ListLangContextBuilder builder = new ListLangContextBuilder();
        for (int i = 0; i < length; i++) {
            builder.addLang(langArray[i]);
        }
        return builder.toListLangContext();
    }

    public static ListLangContext build(Langs langs) {
        if (langs.isEmpty()) {
            throw new IllegalArgumentException("langList.getLangCount() == 0");
        }
        ListLangContextBuilder builder = new ListLangContextBuilder();
        builder.addLangs(langs);
        return builder.toListLangContext();
    }


    private static class InternalListLangContext extends AbstractList<ListLangContext.Unit> implements ListLangContext {

        private final ListLangContext.Unit[] unitArray;

        private InternalListLangContext(ListLangContext.Unit[] unitArray) {
            this.unitArray = unitArray;
        }

        @Override
        public int size() {
            return unitArray.length;
        }

        @Override
        public ListLangContext.Unit get(int index) {
            return unitArray[index];
        }

    }


    private static class InternalUnit implements ListLangContext.Unit {

        private final Lang lang;
        private final Locale formatLocale;

        private InternalUnit(Lang lang, Locale formatLocale) {
            this.lang = lang;
            this.formatLocale = formatLocale;
        }

        @Override
        public Lang getLang() {
            return lang;
        }

        @Override
        public Locale getFormatLocale() {
            return formatLocale;
        }

    }

}
