/* FichothequeLib_Tools - Copyright (c) 2012-2021 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.fichotheque.tools.format.patterndefs;

import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import net.fichotheque.format.PatternDef;
import net.mapeadores.util.text.StringUtils;


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

    private final Map<String, ParameterDefBuilder> builderMap = new LinkedHashMap<String, ParameterDefBuilder>();
    private final String name;
    private String directValueType = null;


    public PatternDefBuilder(String name) {
        this.name = name;
    }

    public PatternDefBuilder setDirectValueType(String directValueType) {
        this.directValueType = directValueType;
        return this;
    }

    public PatternDefBuilder addParameter(String name, String... availableValues) {
        ParameterDefBuilder builder = builderMap.get(name);
        if (builder == null) {
            builder = new ParameterDefBuilder(name);
            builderMap.put(name, builder);
        }
        builder.add(availableValues);
        return this;
    }

    public PatternDef toPatternDef() {
        int size = builderMap.size();
        PatternDef.ParameterDef[] array = new PatternDef.ParameterDef[size];
        int p = 0;
        for (ParameterDefBuilder builder : builderMap.values()) {
            array[p] = builder.toParameterDef();
            p++;
        }
        return new InternalPatternDef(name, directValueType, PatternDefUtils.wrap(array));
    }

    public static PatternDefBuilder init(String name) {
        return new PatternDefBuilder(name);
    }


    private static class InternalPatternDef implements PatternDef {

        private final String name;
        private final String directValueType;
        private final List<PatternDef.ParameterDef> parameterDefList;

        private InternalPatternDef(String name, String parametersFamily, List<PatternDef.ParameterDef> parameterDefList) {
            this.name = name;
            this.directValueType = parametersFamily;
            this.parameterDefList = parameterDefList;
        }

        @Override
        public String getName() {
            return name;
        }

        @Override
        public String getDirectValueType() {
            return directValueType;
        }

        @Override
        public List<ParameterDef> getParameterDefList() {
            return parameterDefList;
        }

    }


    private static class ParameterDefBuilder {

        private final String name;
        private final Set<String> valueSet = new LinkedHashSet<String>();

        private ParameterDefBuilder(String name) {
            this.name = name;
        }

        private ParameterDefBuilder add(String... values) {
            if (values != null) {
                for (String value : values) {
                    valueSet.add(value);
                }
            }
            return this;
        }

        private PatternDef.ParameterDef toParameterDef() {
            List<String> finalList = StringUtils.toList(valueSet);
            return new InternalParameterDef(name, finalList);
        }

    }


    private static class InternalParameterDef implements PatternDef.ParameterDef {

        private final String name;
        private final List<String> availableValueList;

        private InternalParameterDef(String name, List<String> availableValueList) {
            this.name = name;
            this.availableValueList = availableValueList;
        }

        @Override
        public String getName() {
            return name;
        }

        @Override
        public List<String> getAvailableValueList() {
            return availableValueList;
        }

    }


}
