/* BdfServer - Copyright (c) 2024-2025 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 fr.exemole.bdfserver.tools.ficheform.builders;

import fr.exemole.bdfserver.api.ficheform.FicheFormParameters;
import fr.exemole.bdfserver.api.ficheform.ThesaurusIncludeElement;
import fr.exemole.bdfserver.api.ui.IncludeUi;
import fr.exemole.bdfserver.api.ui.SubsetIncludeUi;
import fr.exemole.bdfserver.tools.ficheform.FicheFormUtils;
import java.util.AbstractList;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.RandomAccess;
import java.util.Set;
import net.fichotheque.croisement.Croisements;
import net.fichotheque.croisement.Liaison;
import net.fichotheque.include.ExtendedIncludeKey;
import net.fichotheque.thesaurus.Motcle;
import net.fichotheque.thesaurus.Thesaurus;
import net.fichotheque.utils.CroisementUtils;
import net.mapeadores.util.text.StringUtils;


/**
 *
 * @author Vincent Calame
 */
class MotcleEntryListBuilder {

    private final List<InternalEntry> entryList = new ArrayList<InternalEntry>();

    MotcleEntryListBuilder() {

    }

    boolean isEmpty() {
        return entryList.isEmpty();
    }

    void add(Motcle motcle, int weight) {
        String idalpha = motcle.getIdalpha();
        String value;
        if (idalpha != null) {
            value = idalpha;
        } else {
            value = String.valueOf(motcle.getId());
        }
        if (weight > 1) {
            value = value + "<" + weight + ">";
        }
        entryList.add(new InternalEntry(motcle, weight, value));
    }

    void populateDefault(FicheFormParameters ficheFormParameters, IncludeUi includeUi, Thesaurus thesaurus) {
        String defaultValue = FicheFormUtils.getDefVal(ficheFormParameters, includeUi);
        if (defaultValue.length() == 0) {
            return;
        }
        String[] tokens = StringUtils.getTokens(defaultValue, ';', StringUtils.EMPTY_EXCLUDE);
        Set<Motcle> defaultSet = new HashSet<Motcle>();
        boolean withIdalpha = thesaurus.isIdalphaType();
        for (String token : tokens) {
            if (withIdalpha) {
                Motcle motcle = thesaurus.getMotcleByIdalpha(token);
                if (motcle != null) {
                    if (!defaultSet.contains(motcle)) {
                        defaultSet.add(motcle);
                        add(motcle, -1);
                    }
                }
            } else {
                try {
                    int motcleid = Integer.parseInt(token);
                    Motcle motcle = thesaurus.getMotcleById(motcleid);
                    if (motcle != null) {
                        if (!defaultSet.contains(motcle)) {
                            defaultSet.add(motcle);
                            add(motcle, -1);
                        }
                    }
                } catch (NumberFormatException nfe) {
                }
            }
        }
    }

    Collection<Liaison> populate(Croisements motcleCroisements, SubsetIncludeUi includeUi, boolean withWeight) {
        ExtendedIncludeKey extendedIncludeKey = includeUi.getExtendedIncludeKey();
        Collection<Liaison> liaisons = CroisementUtils.filter(motcleCroisements, extendedIncludeKey);
        if ((!withWeight) || (extendedIncludeKey.hasWeightFilter())) {
            for (Liaison liaison : liaisons) {
                add((Motcle) liaison.getSubsetItem(), -1);
            }
        } else {
            for (Liaison liaison : liaisons) {
                add((Motcle) liaison.getSubsetItem(), liaison.getLien().getWeight());
            }
        }
        return liaisons;
    }

    List<ThesaurusIncludeElement.Entry> toList() {
        return wrap(entryList.toArray(new InternalEntry[entryList.size()]));
    }

    private static List<ThesaurusIncludeElement.Entry> wrap(ThesaurusIncludeElement.Entry[] array) {
        return new EntryList(array);
    }


    private static class InternalEntry implements ThesaurusIncludeElement.Entry {

        private final Motcle motcle;
        private final int weight;
        private final String value;

        private InternalEntry(Motcle motcle, int weight, String value) {
            this.motcle = motcle;
            this.weight = weight;
            this.value = value;
        }

        @Override
        public Motcle getMotcle() {
            return motcle;
        }

        @Override
        public int getWeight() {
            return weight;
        }

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

    }


    private static class EntryList extends AbstractList<ThesaurusIncludeElement.Entry> implements RandomAccess {

        private final ThesaurusIncludeElement.Entry[] array;

        private EntryList(ThesaurusIncludeElement.Entry[] array) {
            this.array = array;
        }

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

        @Override
        public ThesaurusIncludeElement.Entry get(int index) {
            return array[index];
        }

    }

}
