/* 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.ItemFieldElement;
import fr.exemole.bdfserver.api.ui.FieldUi;
import fr.exemole.bdfserver.tools.L10nUtils;
import fr.exemole.bdfserver.tools.ficheform.FicheFormUtils;
import net.fichotheque.SubsetKey;
import net.fichotheque.corpus.metadata.CorpusField;
import net.fichotheque.pointeurs.FichePointeur;
import net.fichotheque.sphere.Redacteur;
import net.mapeadores.util.annotation.Nullable;
import net.mapeadores.util.attr.AttributeUtils;
import net.mapeadores.util.attr.Attributes;


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

    private final CorpusField corpusField;
    private String label = "";
    private boolean mandatory;
    private String value = "";
    private boolean redimAllowed;
    private int rows;
    private String widthType;
    private SubsetKey sphereKey;
    private Attributes attributes = AttributeUtils.EMPTY_ATTRIBUTES;

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

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

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

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

    public ItemFieldElementBuilder setValue(String value) {
        if (value == null) {
            throw new IllegalArgumentException("value is null");
        }
        this.value = value;
        return this;
    }

    public ItemFieldElementBuilder setRedimAllowed(boolean redimAllowed) {
        this.redimAllowed = redimAllowed;
        return this;
    }

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

    public ItemFieldElementBuilder setWidthType(String widthType) {
        this.widthType = widthType;
        return this;
    }

    public ItemFieldElementBuilder setSphereKey(SubsetKey sphereKey) {
        this.sphereKey = sphereKey;
        return this;
    }

    public ItemFieldElement toItemFieldElement() {
        return new InternalItemFieldElement(corpusField, label, mandatory, attributes, value, redimAllowed, rows, widthType, sphereKey);
    }

    public static ItemFieldElementBuilder check(FichePointeur fichePointeur, FicheFormParameters ficheFormParameters, CorpusField corpusField, FieldUi fieldUi, @Nullable String defaultValue) {
        boolean redimAllowed = getDefaultRedimAllowed(corpusField);
        String value;
        if (fichePointeur.isEmpty()) {
            if (defaultValue != null) {
                value = defaultValue;
            } else {
                value = FicheFormUtils.getDefVal(fichePointeur, ficheFormParameters, fieldUi);
            }
        } else {
            value = FicheFormUtils.getStringValue(fichePointeur, corpusField, ficheFormParameters);
        }
        int rows = FicheFormUtils.checkRows(fieldUi, (redimAllowed) ? value.length() : -1);;
        if ((rows == 1) && (corpusField.isBlockDisplayInfoField())) {
            rows = 3;
        }
        SubsetKey defaultSphereKey = null;
        if (corpusField.isType(CorpusField.PERSON_FIELD)) {
            defaultSphereKey = corpusField.getDefaultSphereKey();
            if (defaultSphereKey == null) {
                Redacteur defaultRedacteur = ficheFormParameters.getDefaultRedacteur();
                if (defaultRedacteur != null) {
                    defaultSphereKey = defaultRedacteur.getSubsetKey();
                }
            }
        }
        if ((value.isEmpty()) && (fieldUi.isObsolete())) {
            return null;
        }
        return init(corpusField)
                .setRedimAllowed(redimAllowed)
                .setValue(value)
                .setRows(rows)
                .setSphereKey(defaultSphereKey)
                .setMandatory(fieldUi.isMandatory())
                .setAttributes(fieldUi.getAttributes())
                .setLabel(L10nUtils.toLabelString(ficheFormParameters, corpusField))
                .setWidthType(FicheFormUtils.getWidth(fieldUi));
    }

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

    private static boolean getDefaultRedimAllowed(CorpusField corpusField) {
        if (!corpusField.isProp()) {
            return true;
        }
        switch (corpusField.getFicheItemType()) {
            case CorpusField.ITEM_FIELD:
            case CorpusField.PARA_FIELD:
                return true;
            default:
                return false;
        }
    }


    private static class InternalItemFieldElement implements ItemFieldElement {

        private final CorpusField corpusField;
        private final String label;
        private final boolean mandatory;
        private final Attributes attributes;
        private final String value;
        private final boolean redimAllowed;
        private final int rows;
        private final String widthType;
        private final SubsetKey sphereKey;

        private InternalItemFieldElement(CorpusField corpusField, String label, boolean mandatory, Attributes attributes, String value, boolean redimAllowed, int rows, String widthType, SubsetKey sphereKey) {
            this.corpusField = corpusField;
            this.label = label;
            this.mandatory = mandatory;
            this.attributes = attributes;
            this.value = value;
            this.redimAllowed = redimAllowed;
            this.rows = rows;
            this.widthType = widthType;
            this.sphereKey = sphereKey;
        }

        @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 getValue() {
            return value;
        }

        @Override
        public boolean isRedimAllowed() {
            return redimAllowed;
        }

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

        @Override
        public String getWidthType() {
            return widthType;
        }

        @Override
        public SubsetKey getSphereKey() {
            return sphereKey;
        }

    }

}
