/* FichothequeLib_Tools - Copyright (c) 2020-2022 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.tools.duplication;

import net.fichotheque.Fichotheque;
import net.fichotheque.Subset;
import net.fichotheque.SubsetItem;
import net.fichotheque.SubsetKey;
import net.fichotheque.corpus.metadata.FieldKey;
import net.fichotheque.croisement.CroisementEditor;
import net.fichotheque.croisement.Croisements;
import net.fichotheque.croisement.Lien;
import net.fichotheque.eligibility.SubsetEligibility;
import net.fichotheque.pointeurs.FichePointeur;
import net.fichotheque.pointeurs.SubsetItemPointeur;
import net.fichotheque.tools.FichothequeTools;
import net.fichotheque.tools.croisement.CroisementChangeEngine;
import net.fichotheque.utils.CroisementUtils;


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

    private DuplicationUtils() {

    }

    public static void copyCroisements(CroisementEditor croisementEditor, SubsetMatch subsetMatch, SubsetEligibility subsetEligibility) {
        for (SubsetMatch.Entry entry : subsetMatch.getEntryList()) {
            FichothequeTools.copyCroisements(croisementEditor, entry.getOrigin(), entry.getDestination(), subsetEligibility);
        }
    }

    public static void linkToOrigin(CroisementEditor croisementEditor, SubsetMatch subsetMatch, String mode, int weight) {
        for (SubsetMatch.Entry entry : subsetMatch.getEntryList()) {
            SubsetItem destination = entry.getDestination();
            CroisementChangeEngine cce = CroisementChangeEngine.appendOrWeightReplaceEngine(destination);
            cce.addLien(entry.getOrigin(), mode, weight);
            croisementEditor.updateCroisements(destination, cce.toCroisementChanges());

        }
    }

    public static void replicateLinks(CroisementEditor croisementEditor, SubsetMatch subsetMatch) {
        Subset originSubset = subsetMatch.getOriginSubset();
        Fichotheque fichotheque = originSubset.getFichotheque();
        for (SubsetMatch.Entry entry : subsetMatch.getEntryList()) {
            SubsetItem origin = entry.getOrigin();
            Croisements croisements = fichotheque.getCroisements(origin, originSubset);
            if (!croisements.isEmpty()) {
                SubsetItem destination = entry.getDestination();
                CroisementChangeEngine initialCroisementChangeEngine = CroisementChangeEngine.appendOrWeightReplaceEngine(destination);
                for (Croisements.Entry croisementEntry : croisements.getEntryList()) {
                    SubsetItem other = croisementEntry.getSubsetItem();
                    if (other.getId() > origin.getId()) {
                        SubsetMatch.Entry otherEntry = subsetMatch.getEntryByOrigin(other.getId());
                        if (otherEntry != null) {
                            for (Lien lien : croisementEntry.getCroisement().getLienList()) {
                                initialCroisementChangeEngine.addLien(otherEntry.getDestination(), lien.getMode(), lien.getWeight());
                            }
                        }
                    }
                }
                croisementEditor.updateCroisements(destination, initialCroisementChangeEngine.toCroisementChanges());
            }
        }
    }

    public static FichePointeur getFilteredFichePointeur(FichePointeur fichePointeur, DuplicationFilter duplicationFilter) {
        return new FilteredFichePointeur(fichePointeur, duplicationFilter);
    }


    private static class FilteredFichePointeur implements FichePointeur {

        private final FichePointeur originalFichePointeur;
        private final DuplicationFilter duplicationFilter;

        private FilteredFichePointeur(FichePointeur originalFichePointeur, DuplicationFilter duplicationFilter) {
            this.originalFichePointeur = originalFichePointeur;
            this.duplicationFilter = duplicationFilter;
        }

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

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

        @Override
        public Object getValue(FieldKey fieldKey) {
            if (duplicationFilter.getFieldPredicate().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 Croisements getCroisements(Subset subset) {
            if (duplicationFilter.getSubsetEligibility().accept(subset)) {
                return originalFichePointeur.getCroisements(subset);
            } else {
                return CroisementUtils.EMPTY_CROISEMENTS;
            }
        }

        @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);
        }


    }

}
