/* UtilLib - Copyright (c) 2011-2023 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.attr;

import java.util.AbstractList;
import java.util.ArrayList;
import java.util.List;
import java.util.RandomAccess;
import net.mapeadores.util.text.CleanedString;


/**
 *
 * @author Vincent Calame
 */
public class AttributeBuilder extends AbstractList<String> implements RandomAccess {

    private final AttributeKey attributeKey;
    private final List<String> valList = new ArrayList<String>();

    public AttributeBuilder(AttributeKey attributeKey) {
        if (attributeKey == null) {
            throw new IllegalArgumentException("attributeKey is null");
        }
        this.attributeKey = attributeKey;
    }

    @Override
    public void clear() {
        valList.clear();
    }

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

    @Override
    public String get(int index) {
        return valList.get(index);
    }

    public boolean addValue(String value) {
        if (value == null) {
            return false;
        }
        CleanedString cleanedString = CleanedString.newInstance(value);
        if (cleanedString == null) {
            return false;
        }
        valList.add(cleanedString.toString());
        return true;
    }

    public void addValue(CleanedString cleanedString) {
        if (cleanedString == null) {
            throw new IllegalArgumentException("cleanedString is null");
        }
        valList.add(cleanedString.toString());
    }

    public Attribute toAttribute() {
        int size = valList.size();
        if (size == 0) {
            return null;
        }
        if (size == 1) {
            return new SingletonAttribute(attributeKey, valList.get(0));
        }
        String[] valueArray = valList.toArray(new String[size]);
        return new ArrayAttribute(attributeKey, valueArray);
    }

    public static Attribute toAttribute(AttributeKey key, String value) {
        if (value == null) {
            return null;
        }
        CleanedString cs = CleanedString.newInstance(value);
        if (cs == null) {
            return null;
        }
        return toAttribute(key, cs);
    }

    public static Attribute toAttribute(AttributeKey key, CleanedString cleanedString) {
        if (key == null) {
            throw new IllegalArgumentException("key is null");
        }
        if (cleanedString == null) {
            throw new IllegalArgumentException("cleanedString is null");
        }
        return new SingletonAttribute(key, cleanedString.toString());
    }


    private static class SingletonAttribute extends AbstractList<String> implements Attribute {

        private final AttributeKey key;
        private final String value;

        private SingletonAttribute(AttributeKey key, String value) {
            this.key = key;
            this.value = value;
        }

        @Override
        public AttributeKey getAttributeKey() {
            return key;
        }

        @Override
        public String getFirstValue() {
            return value;
        }

        @Override
        public int size() {
            return 1;
        }

        @Override
        public String get(int i) {
            if (i != 0) {
                throw new IndexOutOfBoundsException();
            }
            return value;
        }

    }


    private static class ArrayAttribute extends AbstractList<String> implements Attribute {

        private final AttributeKey key;
        private final String[] valueArray;

        private ArrayAttribute(AttributeKey key, String[] valueArray) {
            this.key = key;
            this.valueArray = valueArray;
        }

        @Override
        public AttributeKey getAttributeKey() {
            return key;
        }

        @Override
        public String getFirstValue() {
            return valueArray[0];
        }

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

        @Override
        public String get(int i) {
            return valueArray[i];
        }

    }

}
