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

import fr.exemole.bdfserver.api.ficheform.FicheFormParameters;
import fr.exemole.bdfserver.api.ficheform.FormElement;
import fr.exemole.bdfserver.api.ficheform.FormElementProvider;
import fr.exemole.bdfserver.api.instruction.OutputParameters;
import fr.exemole.bdfserver.api.ui.FieldUi;
import fr.exemole.bdfserver.api.ui.IncludeUi;
import fr.exemole.bdfserver.api.ui.SpecialIncludeUi;
import fr.exemole.bdfserver.api.ui.SubsetIncludeUi;
import fr.exemole.bdfserver.tools.ficheform.builders.AddendaIncludeElementBuilder;
import fr.exemole.bdfserver.tools.ficheform.builders.AlbumIncludeElementBuilder;
import fr.exemole.bdfserver.tools.ficheform.builders.CorpusIncludeElementBuilder;
import fr.exemole.bdfserver.tools.ficheform.builders.GeopointPropSubfieldsElementBuilder;
import fr.exemole.bdfserver.tools.ficheform.builders.ImagePropSubfieldsElementBuilder;
import fr.exemole.bdfserver.tools.ficheform.builders.LangFieldElementBuilder;
import fr.exemole.bdfserver.tools.ficheform.builders.AmountInfoSubfieldsElementBuilder;
import fr.exemole.bdfserver.tools.ficheform.builders.AmountPropSubfieldsElementBuilder;
import fr.exemole.bdfserver.tools.ficheform.builders.PersonnePropSubfieldElementBuilder;
import net.fichotheque.FichothequeConstants;
import net.fichotheque.SubsetKey;
import net.fichotheque.corpus.metadata.CorpusField;
import net.fichotheque.corpus.metadata.FieldKey;
import net.fichotheque.pointeurs.FichePointeur;
import net.fichotheque.utils.CorpusMetadataUtils;


/**
 *
 * @author Vincent Calame
 */
public final class FormElementProviderFactory {

    private FormElementProviderFactory() {
    }

    public static FormElementProvider newInstance(OutputParameters outputParameters) {
        return newInstance(FicheFormUtils.toFicheFormParameters(outputParameters));
    }

    public static FormElementProvider newInstance(FicheFormParameters ficheFormParameters) {
        return new InternalFormElementProvider(ficheFormParameters);
    }


    private static class InternalFormElementProvider implements FormElementProvider {

        private final FicheFormParameters ficheFormParameters;

        public InternalFormElementProvider(FicheFormParameters ficheFormParameters) {
            this.ficheFormParameters = ficheFormParameters;
        }

        @Override
        public FormElement.Include getFormElement(FichePointeur fichePointeur, IncludeUi includeUi) {
            if (includeUi instanceof SpecialIncludeUi) {
                SpecialIncludeUi specialIncludeUi = (SpecialIncludeUi) includeUi;
                if (!FicheFormUtils.hasAccess(ficheFormParameters, specialIncludeUi)) {
                    return null;
                }
                switch (specialIncludeUi.getName()) {
                    case FichothequeConstants.LIAGE_NAME:
                        CorpusIncludeElementBuilder cieb = CorpusIncludeElementBuilder.check(fichePointeur, ficheFormParameters, specialIncludeUi);
                        if (cieb != null) {
                            return cieb.toCorpusIncludeElement();
                        } else {
                            return null;
                        }
                    case FichothequeConstants.PARENTAGE_NAME:
                        return null;
                    default:
                        return null;
                }
            } else if (includeUi instanceof SubsetIncludeUi) {
                SubsetIncludeUi subsetIncludeUi = (SubsetIncludeUi) includeUi;
                if (!FicheFormUtils.hasAccess(ficheFormParameters, subsetIncludeUi)) {
                    return null;
                }
                switch (subsetIncludeUi.getCategory()) {
                    case SubsetKey.CATEGORY_ADDENDA:
                        AddendaIncludeElementBuilder adieb = AddendaIncludeElementBuilder.check(fichePointeur, ficheFormParameters, subsetIncludeUi);
                        if (adieb != null) {
                            return adieb.toAddendaIncludeElement();
                        } else {
                            return null;
                        }
                    case SubsetKey.CATEGORY_ALBUM:
                        AlbumIncludeElementBuilder alieb = AlbumIncludeElementBuilder.check(fichePointeur, ficheFormParameters, subsetIncludeUi);
                        if (alieb != null) {
                            return alieb.toAlbumIncludeElement();
                        } else {
                            return null;
                        }
                    case SubsetKey.CATEGORY_CORPUS:
                        CorpusIncludeElementBuilder cieb = CorpusIncludeElementBuilder.check(fichePointeur, ficheFormParameters, subsetIncludeUi);
                        if (cieb != null) {
                            return cieb.toCorpusIncludeElement();
                        } else {
                            return null;
                        }
                    case SubsetKey.CATEGORY_THESAURUS:
                        return FicheFormUtils.toThesaurusIncludeElement(fichePointeur, ficheFormParameters, subsetIncludeUi);
                    default:
                        return null;
                }
            } else {
                return null;
            }
        }

        @Override
        public FormElement.Field getFormElement(FichePointeur fichePointeur, FieldUi fieldUi) {
            CorpusField corpusField = FicheFormUtils.getCorpusField(fichePointeur, fieldUi);
            if (corpusField == null) {
                return null;
            }
            if (corpusField.isGenerated()) {
                return null;
            }
            if (!FicheFormUtils.hasAccess(ficheFormParameters, fieldUi)) {
                return null;
            }
            switch (corpusField.getFieldString()) {
                case FieldKey.SPECIAL_ID:
                    return null;
                case FieldKey.SPECIAL_LANG:
                    return LangFieldElementBuilder.build(fichePointeur, ficheFormParameters, corpusField, fieldUi)
                            .toLangFieldElement();
            }
            if ((corpusField.isProp()) && (corpusField.isSubfieldDisplay())) {
                switch (corpusField.getFicheItemType()) {
                    case CorpusField.PERSON_FIELD: {
                        PersonnePropSubfieldElementBuilder builder = PersonnePropSubfieldElementBuilder.check(fichePointeur, ficheFormParameters, corpusField, fieldUi);
                        if (builder != null) {
                            return builder.toPersonnePropSubfieldsElement();
                        } else {
                            return null;
                        }
                    }
                    case CorpusField.GEOPOINT_FIELD: {
                        GeopointPropSubfieldsElementBuilder builder = GeopointPropSubfieldsElementBuilder.check(fichePointeur, ficheFormParameters, corpusField, fieldUi);
                        if (builder != null) {
                            return builder.toGeopointPropSubfieldsElement();
                        } else {
                            return null;
                        }
                    }
                    case CorpusField.IMAGE_FIELD: {
                        ImagePropSubfieldsElementBuilder builder = ImagePropSubfieldsElementBuilder.check(fichePointeur, ficheFormParameters, corpusField, fieldUi);
                        if (builder != null) {
                            return builder.toImagePropSubfieldsElement();
                        } else {
                            return null;
                        }
                    }
                }
            }
            if (CorpusMetadataUtils.isCurrenciesProp(corpusField)) {
                AmountPropSubfieldsElementBuilder builder = AmountPropSubfieldsElementBuilder.check(fichePointeur, ficheFormParameters, corpusField, fieldUi);
                if (builder != null) {
                    return builder.toAmountPropSubfieldsElement();
                } else {
                    return null;
                }
            }
            if (CorpusMetadataUtils.isCurrenciesInfo(corpusField)) {
                AmountInfoSubfieldsElementBuilder builder = AmountInfoSubfieldsElementBuilder.check(fichePointeur, ficheFormParameters, corpusField, fieldUi);
                if (builder != null) {
                    return builder.toAmountInfoSubfieldsElement();
                } else {
                    return null;
                }
            }
            return FicheFormUtils.toFormElement(fichePointeur, ficheFormParameters, corpusField, fieldUi);
        }

    }

}
