/* FichothequeLib_API - Copyright (c) 2006-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 net.fichotheque.corpus.metadata;

import java.text.ParseException;
import java.util.Set;
import net.fichotheque.SubsetKey;
import net.fichotheque.utils.CorpusMetadataUtils;
import net.mapeadores.util.localisation.Langs;
import net.mapeadores.util.money.Currencies;
import net.mapeadores.util.text.Labels;
import net.mapeadores.util.text.MultiStringable;
import net.mapeadores.util.text.StringUtils;


/**
 *
 * @author Vincent Calame
 */
public interface CorpusField {

    public final static String ITEM_FIELD = "item";
    public final static String PERSON_FIELD = "person";
    public final static String LANGUAGE_FIELD = "language";
    public final static String COUNTRY_FIELD = "country";
    public final static String DATE_FIELD = "date";
    public final static String EMAIL_FIELD = "email";
    public final static String LINK_FIELD = "link";
    public final static String NUMBER_FIELD = "number";
    public final static String AMOUNT_FIELD = "amount";
    public final static String GEOPOINT_FIELD = "geopoint";
    public final static String PARA_FIELD = "para";
    public final static String IMAGE_FIELD = "image";

    public FieldKey getFieldKey();

    public Labels getLabels();

    public Set<String> getOptionNameSet();

    /**
     * Instance de String ou MultiStringable
     */
    public Object getOption(String optionName);

    public CorpusMetadata getCorpusMetadata();

    /**
     * Le champ des rédacteurs retourne PERSONNE_FIELD, le champ Langue retourne
     * LANGUE_FIELD.
     *
     */
    public String getFicheItemType();

    public boolean isGenerated();

    public default boolean isSpecial() {
        return getFieldKey().isSpecial();
    }

    public default boolean isProp() {
        return getFieldKey().isProp();
    }

    public default boolean isInfo() {
        return getFieldKey().isInfo();
    }

    public default boolean isSection() {
        return getFieldKey().isSection();
    }

    public default String getFieldName() {
        return getFieldKey().getFieldName();
    }

    public default String getFieldString() {
        return getFieldKey().getKeyString();
    }

    public default short getCategory() {
        return getFieldKey().getCategory();
    }

    public default String getCategoryString() {
        return FieldKey.categoryToString(getFieldKey().getCategory());
    }

    public default String getStringOption(String optionName) {
        return (String) getOption(optionName);
    }

    public default boolean isBlockDisplayInfoField() {
        if (!isInfo()) {
            return false;
        }
        String value = getStringOption(FieldOptionConstants.INFODISPLAY_OPTION);
        if (value == null) {
            return false;
        }
        return (value.equals(FieldOptionConstants.BLOCK_DISPLAY));
    }

    public default boolean isType(String ficheItemType) {
        return getFicheItemType().equals(ficheItemType);
    }

    /**
     * Retourne l'étendue des langues disponibles pour les champs traitant des
     * langues. Les trois valeurs possibles sont:
     * <ul>
     * <li>FieldOptionsConstants.ALL_SCOPE : toutes les langues sont disponibles
     * <li>FieldOptionsConstants.CONFIG_SCOPE : les langues disponibles sont
     * celles de la configuration globale
     * <li>FieldOptionsConstants.LIST_SCOPE : les langues disponibles sont
     * définies par la liste retournée par getLangs() (sa valeur ne doit
     * impérativement pas être nulle)
     * </ul>
     * <p>
     * Cette méthode doit retourner une valeur pour le champ de la langue de la
     * fiche (FieldKey.LANG) et pour tous les champs Information ou Propriété de
     * type langue et nul pour tous les autres champs.
     * <p>
     * La valeur par défaut est différente suivant les champs : pour le champ de
     * la langue de la fiche (FieldKey.LANG), elle est vaut
     * FieldOptionsConstants.CONFIG_SCOPE et elle vaut
     * FieldOptionsConstants.ALL_SCOPE pour tous les autres champs de type
     * langue.
     *
     * @return l'indication de l'étendue des langues disponibles ou nul si le
     * champ n'est pas concerné
     */
    public default String getLangScope() {
        if (!isType(CorpusField.LANGUAGE_FIELD)) {
            return null;
        }
        String value = getStringOption(FieldOptionConstants.LANGSCOPE_OPTION);
        if (value == null) {
            return CorpusMetadataUtils.getDefaultLangScope(getFieldKey());
        }
        return value;
    }

    /**
     * Indique si le champ doit être décomposé en sous-champ dans lors de la
     * saisie. Cette option n'est pertinente que pour les Propriétés dont le
     * type possède des sous-champs (par exemple, un propriété de type «
     * Geopoint » possède deux sous-champs : la latitude et la longitude).
     *
     * @return true si la décomposition en sous-champ doit être utilisée, false
     * sinon
     */
    public default boolean isSubfieldDisplay() {
        String value = getStringOption(FieldOptionConstants.SUBFIELDDISPLAY_OPTION);
        return StringUtils.isTrue(value);
    }

    /**
     * Retourne la sphère par défaut pour le traitement des champs de type «
     * Personne ». Peut être nul (et dans ce cas la sphère par défaut sera celle
     * du rédacteur intervenant sur la fiche). SubsetKey doit désigner une
     * sphère et non une autre collecion.
     *
     * @return un objet SubsetKey indentifiant la sphère par défaut ou null
     */
    public default SubsetKey getDefaultSphereKey() {
        String value = getStringOption(FieldOptionConstants.DEFAULTSPHEREKEY_OPTION);
        if (value == null) {
            return null;
        }
        try {
            SubsetKey sphereKey = SubsetKey.parse(value);
            if (!sphereKey.isSphereSubset()) {
                return null;
            }
            return sphereKey;
        } catch (ParseException pe) {
            return null;
        }
    }

    /**
     * Retourne la liste des monnaies acceptées par le champ. Peut être nul mais
     * pas de longueur nul.
     *
     * @return une instance de Currencies listant les monnaies acceptées ou null
     */
    public default Currencies getCurrencies() {
        Object value = getOption(FieldOptionConstants.CURRENCYARRAY_OPTION);
        if (value == null) {
            return null;
        }
        return (Currencies) value;
    }

    public default Langs getLangs() {
        Object value = getOption(FieldOptionConstants.LANGARRAY_OPTION);
        if (value == null) {
            return null;
        }
        return (Langs) value;
    }

    /**
     * Retourne la liste des champs permettant de construire une adresse. Cette
     * options est utilisée pour le géocodage. L'adresse de géocodage sera
     * construite en concaténant les valeurs des champs indiqués par l'instance
     * de MultiStringable. Peut être nul.
     *
     * @return une instance de MultiStringable listant les champs pour
     * construire une adresse ou null
     */
    public default MultiStringable getAddressFieldNames() {
        Object value = getOption(FieldOptionConstants.ADDRESSFIELDARRAY_OPTION);
        if (value == null) {
            return null;
        }
        return (MultiStringable) value;
    }

    public static String checkFicheItemType(String ficheItemType) {
        switch (ficheItemType) {
            case CorpusField.PERSON_FIELD:
            case "personne":
                return CorpusField.PERSON_FIELD;
            case CorpusField.LANGUAGE_FIELD:
            case "langue":
                return CorpusField.LANGUAGE_FIELD;
            case CorpusField.DATE_FIELD:
            case "datation":
                return CorpusField.DATE_FIELD;
            case CorpusField.COUNTRY_FIELD:
            case "pays":
                return CorpusField.COUNTRY_FIELD;
            case CorpusField.EMAIL_FIELD:
            case "courriel":
                return CorpusField.EMAIL_FIELD;
            case CorpusField.LINK_FIELD:
                return CorpusField.LINK_FIELD;
            case CorpusField.ITEM_FIELD:
                return CorpusField.ITEM_FIELD;
            case CorpusField.NUMBER_FIELD:
            case "nombre":
                return CorpusField.NUMBER_FIELD;
            case CorpusField.AMOUNT_FIELD:
            case "montant":
                return CorpusField.AMOUNT_FIELD;
            case CorpusField.GEOPOINT_FIELD:
                return CorpusField.GEOPOINT_FIELD;
            case CorpusField.PARA_FIELD:
                return CorpusField.PARA_FIELD;
            case CorpusField.IMAGE_FIELD:
                return CorpusField.IMAGE_FIELD;
            default:
                throw new IllegalArgumentException("Wrong ficheItemType value : " + ficheItemType);
        }
    }

}
