/* 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.utils;

import java.text.ParseException;
import java.util.ArrayList;
import java.util.List;
import net.fichotheque.SubsetKey;
import net.fichotheque.corpus.metadata.CorpusField;
import net.fichotheque.corpus.metadata.FieldKey;
import net.fichotheque.corpus.metadata.FieldOptionConstants;
import net.fichotheque.corpus.metadata.FieldOptionException;
import net.mapeadores.util.localisation.Lang;
import net.mapeadores.util.localisation.LangsUtils;
import net.mapeadores.util.money.CurrenciesUtils;
import net.mapeadores.util.money.ExtendedCurrency;
import net.mapeadores.util.text.StringUtils;


/**
 * Classe utilitaire de traitement des options.
 *
 * @author Vincent Calame
 */
public final class FieldOptionUtils {


    private FieldOptionUtils() {
    }

    public static boolean haveSubfield(String ficheItemType) {
        switch (ficheItemType) {
            case CorpusField.PERSON_FIELD:
            case CorpusField.GEOPOINT_FIELD:
            case CorpusField.IMAGE_FIELD:
                return true;
            default:
                return false;
        }
    }

    public static boolean testFieldOption(String optionName, CorpusField corpusField) {
        try {
            checkUsage(optionName, corpusField.getFieldKey(), corpusField.getFicheItemType());
            return true;
        } catch (FieldOptionException foe) {
            return false;
        }
    }

    public static boolean testFieldOption(String optionName, FieldKey fieldKey, String ficheItemType) {
        try {
            checkUsage(optionName, fieldKey, ficheItemType);
            return true;
        } catch (FieldOptionException foe) {
            return false;
        }
    }

    public static void checkUsage(String optionName, FieldKey fieldKey, String ficheItemType) throws FieldOptionException {
        switch (optionName) {
            case FieldOptionConstants.INFODISPLAY_OPTION:
                if (!fieldKey.isInfo()) {
                    throw new FieldOptionException("informationDisplay Option applies only to Info Field");
                }
                break;
            case FieldOptionConstants.DEFAULTSPHEREKEY_OPTION:
                if (!ficheItemType.equals(CorpusField.PERSON_FIELD)) {
                    throw new FieldOptionException("ficheItemType must be PERSON_FIELD");
                }
                break;
            case FieldOptionConstants.SUBFIELDDISPLAY_OPTION:
                if (!fieldKey.isProp()) {
                    throw new FieldOptionException("subfieldDisplay Option applies only to Prop Field");
                }
                if (!haveSubfield(ficheItemType)) {
                    throw new FieldOptionException("wrong ficheItemType = " + ficheItemType);
                }
                break;
            case FieldOptionConstants.CURRENCYARRAY_OPTION:
                if (!ficheItemType.equals(CorpusField.AMOUNT_FIELD)) {
                    throw new FieldOptionException("ficheItemType must be AMOUNT_FIELD");
                }
                break;
            case FieldOptionConstants.ADDRESSFIELDARRAY_OPTION:
                if (!fieldKey.isProp()) {
                    throw new FieldOptionException("addressFields Option applies only to Prop Field");
                }
                if (!ficheItemType.equals(CorpusField.GEOPOINT_FIELD)) {
                    throw new FieldOptionException("ficheItemType must be GEOPOINT_FIELD");
                }
                break;
            case FieldOptionConstants.BASEURL_OPTION:
                if ((!ficheItemType.equals(CorpusField.IMAGE_FIELD)) && (!ficheItemType.equals(CorpusField.LINK_FIELD))) {
                    throw new FieldOptionException("ficheItemType must be IMAGE_FIELD or lINK_FIELD");
                }
                break;
            case FieldOptionConstants.LANGSCOPE_OPTION:
                if (!isLangField(fieldKey, ficheItemType)) {
                    throw new FieldOptionException("langScope applies only to FieldKey.LANG and fields with ficheItemType = LANGUE_FIELD");
                }
                break;
            case FieldOptionConstants.LANGARRAY_OPTION:
                if ((!isLangField(fieldKey, ficheItemType)) && (ficheItemType != CorpusField.PARA_FIELD)) {
                    throw new FieldOptionException("langArray applies only to FieldKey.LANG and fields with ficheItemType = PARA_FIELD or LANGUE_FIELD");
                }
                break;
            case FieldOptionConstants.GEOLOCALISATIONFIELD_OPTION:
                if ((!fieldKey.isProp()) || (!ficheItemType.equals(CorpusField.GEOPOINT_FIELD))) {
                    throw new FieldOptionException("geolocalisationField applies only to Prop Field with ficheItemType = GEOPOINT_FIELD");
                }
                break;
        }
    }

    public static Object parseOptionValue(String optionName, String optionValue) throws FieldOptionException {
        if (optionValue == null) {
            return null;
        }
        optionValue = optionValue.trim();
        if (optionValue.isEmpty()) {
            return null;
        }
        switch (optionName) {
            case FieldOptionConstants.ADDRESSFIELDARRAY_OPTION: {
                List<FieldKey> fieldKeyList = new ArrayList<FieldKey>();
                String[] tokenArray = StringUtils.getTechnicalTokens(optionValue, false);
                for (String token : tokenArray) {
                    try {
                        FieldKey fieldKey = FieldKey.parse(token);
                        fieldKeyList.add(fieldKey);
                    } catch (java.text.ParseException pe) {
                    }
                }
                if (fieldKeyList.isEmpty()) {
                    return null;
                } else {
                    return fieldKeyList.toArray(new FieldKey[fieldKeyList.size()]);
                }
            }
            case FieldOptionConstants.LANGARRAY_OPTION: {
                Lang[] langArray = LangsUtils.toCleanLangArray(optionValue);
                if (langArray.length == 0) {
                    return null;
                } else {
                    return langArray;
                }
            }
            case FieldOptionConstants.CURRENCYARRAY_OPTION: {
                ExtendedCurrency[] currencyArray = CurrenciesUtils.toCleanCurrencyArray(optionValue);
                if (currencyArray.length == 0) {
                    currencyArray = null;
                }
                return currencyArray;
            }
            default:
                checkString(optionName, optionValue);
                return optionValue;

        }
    }

    public static void checkString(String optionName, String optionValue) throws FieldOptionException {
        switch (optionName) {
            case FieldOptionConstants.DEFAULTSPHEREKEY_OPTION:
                try {
                SubsetKey sphereKey = SubsetKey.parse(optionValue);
                if (!sphereKey.isSphereSubset()) {
                    throw new FieldOptionException("value must be a key of a sphere");
                }
            } catch (ParseException pe) {
                throw new FieldOptionException("value must be a valid sphereKey");
            }
            break;
        }
    }

    private static boolean isLangField(FieldKey fieldKey, String ficheItemType) {
        if (ficheItemType.equals(CorpusField.LANGUAGE_FIELD)) {
            return true;
        }
        switch (fieldKey.getKeyString()) {
            case FieldKey.SPECIAL_LANG:
                return true;
            default:
                return false;
        }
    }

}
