/* BdfServer - Copyright (c) 2009-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.TextFieldElement;
import fr.exemole.bdfserver.api.ui.FieldUi;
import fr.exemole.bdfserver.tools.L10nUtils;
import fr.exemole.bdfserver.tools.ficheform.FicheFormUtils;
import java.io.IOException;
import java.util.Collections;
import java.util.Map;
import net.fichotheque.corpus.fiche.FicheBlocks;
import net.fichotheque.corpus.metadata.CorpusField;
import net.fichotheque.pointeurs.FichePointeur;
import net.fichotheque.syntax.FicheblockSyntax;
import net.fichotheque.syntax.FicheblockSyntaxHandler;
import net.mapeadores.util.annotation.Nullable;
import net.mapeadores.util.attr.AttributeUtils;
import net.mapeadores.util.attr.Attributes;


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

    private final static Map<String, Integer> EMPTY_MAP = Collections.emptyMap();
    private final CorpusField corpusField;
    private String label = "";
    private boolean mandatory = false;
    private String formattedText = "";
    private int rows;
    private Attributes attributes = AttributeUtils.EMPTY_ATTRIBUTES;
    private Map<String, Integer> matchingMap = EMPTY_MAP;

    public TextFieldElementBuilder(CorpusField corpusField) {
        this.corpusField = corpusField;
    }

    public TextFieldElementBuilder setLabel(String label) {
        if (label == null) {
            throw new IllegalArgumentException("label is null");
        }
        this.label = label;
        return this;
    }

    public TextFieldElementBuilder setMandatory(boolean mandatory) {
        this.mandatory = mandatory;
        return this;
    }

    public TextFieldElementBuilder setAttributes(Attributes attributes) {
        if (attributes == null) {
            this.attributes = AttributeUtils.EMPTY_ATTRIBUTES;
        } else {
            this.attributes = attributes;
        }
        return this;
    }

    public TextFieldElementBuilder setFormattedText(String formattedText) {
        if (formattedText == null) {
            throw new IllegalArgumentException("formattedText is null");
        }
        this.formattedText = formattedText;
        return this;
    }

    public TextFieldElementBuilder setRows(int rows) {
        this.rows = rows;
        return this;
    }

    public TextFieldElementBuilder setMatchingMap(Map<String, Integer> matchingMap) {
        if (matchingMap == null) {
            this.matchingMap = EMPTY_MAP;
        } else {
            this.matchingMap = matchingMap;
        }
        return this;
    }

    public TextFieldElement toTextFieldElement() {
        return new InternalTextFieldElement(corpusField, label, mandatory, attributes, formattedText, rows, matchingMap);
    }

    public static TextFieldElementBuilder check(FichePointeur fichePointeur, FicheFormParameters ficheFormParameters, CorpusField corpusField, FieldUi fieldUi, @Nullable String defaultValue) {
        if (!corpusField.isSection()) {
            throw new IllegalArgumentException("!corpusField.isSection()");
        }
        String value;
        Map<String, Integer> matchingMap = EMPTY_MAP;
        if (fichePointeur.isEmpty()) {
            if (defaultValue != null) {
                value = defaultValue;
            } else {
                value = FicheFormUtils.getDefVal(fichePointeur, ficheFormParameters, fieldUi);
            }
        } else {
            FicheBlocks ficheBlocks = (FicheBlocks) fichePointeur.getValue(corpusField);
            if (ficheBlocks == null) {
                value = "";
            } else {
                StringBuilder buf = new StringBuilder();
                FicheblockSyntaxHandler handler = new FicheblockSyntaxHandler(buf);
                try {
                    FicheblockSyntax.appendFicheBlocks(handler, ficheBlocks, ficheFormParameters.getFicheBlockFormSyntaxParameters());
                } catch (IOException ioe) {

                }
                matchingMap = handler.getMatchingMap();
                value = buf.toString();
            }
        }
        if ((value.isEmpty()) && (fieldUi.isObsolete())) {
            return null;
        }
        return init(corpusField)
                .setFormattedText(value)
                .setMandatory(fieldUi.isMandatory())
                .setAttributes(fieldUi.getAttributes())
                .setRows(FicheFormUtils.getRows(fieldUi))
                .setLabel(L10nUtils.toLabelString(ficheFormParameters, corpusField))
                .setMatchingMap(matchingMap);
    }

    public static TextFieldElementBuilder init(CorpusField corpusField) {
        return new TextFieldElementBuilder(corpusField);
    }


    private static class InternalTextFieldElement implements TextFieldElement {

        private final CorpusField corpusField;
        private final String label;
        private final boolean mandatory;
        private final Attributes attributes;
        private final String formattedText;
        private final int rows;
        private final Map<String, Integer> matchingMap;

        public InternalTextFieldElement(CorpusField corpusField, String label, boolean mandatory, Attributes attributes, String formattedText, int rows, Map<String, Integer> matchingMap) {
            this.corpusField = corpusField;
            this.label = label;
            this.mandatory = mandatory;
            this.attributes = attributes;
            this.formattedText = formattedText;
            this.rows = rows;
            this.matchingMap = matchingMap;
        }

        @Override
        public CorpusField getCorpusField() {
            return corpusField;
        }

        @Override
        public String getLabel() {
            return label;
        }

        @Override
        public boolean isMandatory() {
            return mandatory;
        }

        @Override
        public Attributes getAttributes() {
            return attributes;
        }

        @Override
        public String getFormattedText() {
            return formattedText;
        }

        @Override
        public int getRows() {
            return rows;
        }

        @Override
        public Map<String, Integer> getMatchingMap() {
            return matchingMap;
        }

    }

}
