/* FichothequeLib_API - Copyright (c) 2007-2026 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.util.function.Predicate;
import net.fichotheque.Subset;
import net.fichotheque.SubsetItem;
import net.fichotheque.SubsetKey;
import net.fichotheque.corpus.fiche.AmountItem;
import net.fichotheque.corpus.fiche.DateItem;
import net.fichotheque.corpus.fiche.NumberItem;
import net.fichotheque.corpus.metadata.CorpusField;
import net.fichotheque.corpus.metadata.FieldKey;
import net.fichotheque.eligibility.SubsetEligibility;
import net.fichotheque.junction.Junctions;
import net.fichotheque.pointeurs.FichePointeur;
import net.fichotheque.pointeurs.SubsetItemPointeur;


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

    private PointeurUtils() {
    }

    public static SubsetItemPointeur checkMasterPointeur(FichePointeur fichePointeur, boolean master) {
        if (master) {
            Subset masterSubset = fichePointeur.getCorpus().getMasterSubset();
            if (masterSubset != null) {
                return fichePointeur.getParentagePointeur(masterSubset.getSubsetKey());
            } else {
                return fichePointeur;
            }
        } else {
            return fichePointeur;
        }
    }

    public static DateItem getDate(FichePointeur fichePointeur, CorpusField corpusField) {
        return getDate(fichePointeur, corpusField.getFieldKey());
    }

    public static DateItem getDate(FichePointeur fichePointeur, FieldKey fieldKey) {
        Object obj = fichePointeur.getValue(fieldKey);
        if (obj == null) {
            return null;
        }
        if (!(obj instanceof DateItem)) {
            return null;
        }
        return (DateItem) obj;
    }

    public static AmountItem getAmount(FichePointeur fichePointeur, CorpusField corpusField) {
        return getAmount(fichePointeur, corpusField.getFieldKey());
    }

    public static AmountItem getAmount(FichePointeur fichePointeur, FieldKey fieldKey) {
        Object obj = fichePointeur.getValue(fieldKey);
        if (obj == null) {
            return null;
        }
        if (!(obj instanceof AmountItem)) {
            return null;
        }
        return (AmountItem) obj;
    }

    public static NumberItem getNumber(FichePointeur fichePointeur, CorpusField corpusField) {
        return getNumber(fichePointeur, corpusField.getFieldKey());
    }

    public static NumberItem getNumber(FichePointeur fichePointeur, FieldKey fieldKey) {
        Object obj = fichePointeur.getValue(fieldKey);
        if (obj == null) {
            return null;
        }
        if (!(obj instanceof NumberItem)) {
            return null;
        }
        return (NumberItem) obj;
    }

    public static FichePointeur filter(FichePointeur fichePointeur, SubsetEligibility subsetEligibility, Predicate<FieldKey> fieldPredicate) {
        return new FilteredFichePointeur(fichePointeur, subsetEligibility, fieldPredicate);
    }


    private static class FilteredFichePointeur implements FichePointeur {

        private final FichePointeur originalFichePointeur;
        private final SubsetEligibility subsetEligibility;
        private final Predicate<FieldKey> fieldPredicate;

        private FilteredFichePointeur(FichePointeur originalFichePointeur, SubsetEligibility subsetEligibility, Predicate<FieldKey> fieldPredicate) {
            this.originalFichePointeur = originalFichePointeur;
            this.subsetEligibility = subsetEligibility;
            this.fieldPredicate = fieldPredicate;
        }

        @Override
        public boolean isWithSection() {
            return originalFichePointeur.isWithSection();
        }

        @Override
        public void enableCache(boolean enable) {
            originalFichePointeur.enableCache(enable);
        }

        @Override
        public Object getValue(FieldKey fieldKey) {
            if (fieldPredicate.test(fieldKey)) {
                return originalFichePointeur.getValue(fieldKey);
            } else {
                return null;
            }
        }

        @Override
        public SubsetItemPointeur getParentagePointeur(SubsetKey parentageSubsetKey) {
            return originalFichePointeur.getParentagePointeur(parentageSubsetKey);
        }

        @Override
        public SubsetItemPointeur getAssociatedPointeur(Subset subset) {
            return originalFichePointeur.getAssociatedPointeur(subset);
        }

        @Override
        public void setCurrentSubsetItem(int id) {
            originalFichePointeur.setCurrentSubsetItem(id);
        }

        @Override
        public void setCurrentSubsetItem(SubsetItem subsetItem) {
            originalFichePointeur.setCurrentSubsetItem(subsetItem);
        }

        @Override
        public SubsetItem getCurrentSubsetItem() {
            return originalFichePointeur.getCurrentSubsetItem();
        }

        @Override
        public Subset getSubset() {
            return originalFichePointeur.getSubset();
        }

        @Override
        public Junctions getJunctions(Subset subset) {
            if (subsetEligibility.accept(subset)) {
                return originalFichePointeur.getJunctions(subset);
            } else {
                return JunctionUtils.EMPTY_JUNCTIONS;
            }
        }

        @Override
        public Object getCurrentObject(String objectName) {
            return originalFichePointeur.getCurrentObject(objectName);
        }

        @Override
        public void putCurrentObject(String objectName, Object object) {
            originalFichePointeur.putCurrentObject(objectName, object);
        }

        @Override
        public Object getPointeurObject(String objectName) {
            return originalFichePointeur.getPointeurObject(objectName);
        }

        @Override
        public void putPointeurObject(String objectName, Object object) {
            originalFichePointeur.putPointeurObject(objectName, object);
        }


    }

}
