/* 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.eligibility.SubsetEligibility;
import net.fichotheque.pointeurs.FichePointeur;
import net.fichotheque.pointeurs.SubsetItemPointeur;
import net.fichotheque.tools.FichothequeTools;
import net.fichotheque.tools.junction.JunctionChangeEngine;
import net.fichotheque.utils.JunctionUtils;
import net.fichotheque.junction.Tie;
import net.fichotheque.junction.JunctionEditor;
import net.fichotheque.junction.Junctions;


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

    private DuplicationUtils() {

    }

    public static void copyJunctions(JunctionEditor junctionEditor, SubsetMatch subsetMatch, SubsetEligibility subsetEligibility) {
        for (SubsetMatch.Entry entry : subsetMatch.getEntryList()) {
            FichothequeTools.copyJunctions(junctionEditor, entry.getOrigin(), entry.getDestination(), subsetEligibility);
        }
    }

    public static void linkToOrigin(JunctionEditor junctionEditor, SubsetMatch subsetMatch, String mode, int weight) {
        for (SubsetMatch.Entry entry : subsetMatch.getEntryList()) {
            SubsetItem destination = entry.getDestination();
            JunctionChangeEngine cce = JunctionChangeEngine.appendOrWeightReplaceEngine(destination);
            cce.addTie(entry.getOrigin(), mode, weight);
            junctionEditor.updateJunctions(destination, cce.toJunctionChanges());

        }
    }

    public static void replicateLinks(JunctionEditor junctionEditor, SubsetMatch subsetMatch) {
        Subset originSubset = subsetMatch.getOriginSubset();
        Fichotheque fichotheque = originSubset.getFichotheque();
        for (SubsetMatch.Entry entry : subsetMatch.getEntryList()) {
            SubsetItem origin = entry.getOrigin();
            Junctions junctions = fichotheque.getJunctions(origin, originSubset);
            if (!junctions.isEmpty()) {
                SubsetItem destination = entry.getDestination();
                JunctionChangeEngine initialJunctionChangeEngine = JunctionChangeEngine.appendOrWeightReplaceEngine(destination);
                for (Junctions.Entry junctionEntry : junctions.getEntryList()) {
                    SubsetItem other = junctionEntry.getSubsetItem();
                    if (other.getId() > origin.getId()) {
                        SubsetMatch.Entry otherEntry = subsetMatch.getEntryByOrigin(other.getId());
                        if (otherEntry != null) {
                            for (Tie tie : junctionEntry.getJunction().getTieList()) {
                                initialJunctionChangeEngine.addTie(otherEntry.getDestination(), tie.getMode(), tie.getWeight());
                            }
                        }
                    }
                }
                junctionEditor.updateJunctions(destination, initialJunctionChangeEngine.toJunctionChanges());
            }
        }
    }

    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 Junctions getJunctions(Subset subset) {
            if (duplicationFilter.getSubsetEligibility().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);
        }


    }

}
