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

import java.util.ArrayList;
import java.util.List;
import net.fichotheque.Fichotheque;
import net.fichotheque.FichothequeEditor;
import net.fichotheque.Metadata;
import net.fichotheque.MetadataEditor;
import net.fichotheque.Subset;
import net.fichotheque.SubsetItem;
import net.fichotheque.SubsetKey;
import net.fichotheque.addenda.AddendaEditor;
import net.fichotheque.addenda.Document;
import net.fichotheque.album.AlbumEditor;
import net.fichotheque.album.Illustration;
import net.fichotheque.corpus.Corpus;
import net.fichotheque.corpus.FicheMeta;
import net.fichotheque.eligibility.SubsetEligibility;
import net.fichotheque.junction.JunctionChanges;
import net.fichotheque.junction.JunctionEditor;
import net.fichotheque.junction.Junctions;
import net.fichotheque.junction.Tie;
import net.fichotheque.thesaurus.Motcle;
import net.fichotheque.thesaurus.ParentRecursivityException;
import net.fichotheque.thesaurus.Thesaurus;
import net.fichotheque.tools.junction.JunctionChangeEngine;
import net.fichotheque.tools.thesaurus.ThesaurusTools;
import net.fichotheque.utils.FichothequeUtils;
import net.fichotheque.utils.JunctionUtils;
import net.mapeadores.util.attr.Attribute;
import net.mapeadores.util.exceptions.ImplementationException;
import net.mapeadores.util.exceptions.SwitchException;
import net.mapeadores.util.text.CleanedString;
import net.mapeadores.util.text.Label;
import net.mapeadores.util.text.LabelUtils;
import net.mapeadores.util.text.Phrase;


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

    private FichothequeTools() {
    }

    public static boolean remove(FichothequeEditor fichothequeEditor, FicheMeta ficheMeta) {
        Corpus corpus = ficheMeta.getCorpus();
        removeJunctions(fichothequeEditor, ficheMeta);
        int ficheid = ficheMeta.getId();
        for (Corpus satelliteCorpus : corpus.getSatelliteCorpusList()) {
            FicheMeta satelliteFicheMeta = satelliteCorpus.getFicheMetaById(ficheid);
            if (satelliteFicheMeta != null) {
                removeJunctions(fichothequeEditor, satelliteFicheMeta);
                fichothequeEditor.getCorpusEditor(satelliteCorpus).removeFiche(satelliteFicheMeta);
            }
        }
        return fichothequeEditor.getCorpusEditor(corpus).removeFiche(ficheMeta);
    }

    public static boolean remove(FichothequeEditor fichothequeEditor, Motcle motcle) {
        Thesaurus thesaurus = motcle.getThesaurus();
        removeJunctions(fichothequeEditor, motcle);
        int motcleid = motcle.getId();
        for (Corpus corpus : thesaurus.getSatelliteCorpusList()) {
            FicheMeta satelliteFicheMeta = corpus.getFicheMetaById(motcleid);
            if (satelliteFicheMeta != null) {
                FichothequeTools.remove(fichothequeEditor, satelliteFicheMeta);
            }
        }
        try {
            ThesaurusTools.transferChildren(fichothequeEditor, motcle, motcle.getParent());
        } catch (ParentRecursivityException pre) {
            throw new ImplementationException(pre);
        }
        return fichothequeEditor.getThesaurusEditor(thesaurus).removeMotcle(motcle);
    }

    public static boolean remove(FichothequeEditor fichothequeEditor, Document document) {
        removeJunctions(fichothequeEditor, document);
        AddendaEditor addendaEditor = fichothequeEditor.getAddendaEditor(document.getAddenda());
        return addendaEditor.removeDocument(document);
    }

    public static boolean remove(FichothequeEditor fichothequeEditor, Illustration illustration) {
        removeJunctions(fichothequeEditor, illustration);
        AlbumEditor albumEditor = fichothequeEditor.getAlbumEditor(illustration.getAlbum());
        return albumEditor.removeIllustration(illustration);
    }

    private static void removeJunctions(FichothequeEditor fichothequeEditor, SubsetItem subsetItem) {
        JunctionEditor junctionEditor = fichothequeEditor.getJunctionEditor();
        Fichotheque fichotheque = subsetItem.getFichotheque();
        Subset[] subsetArray = FichothequeUtils.toSubsetArray(fichotheque);
        for (Subset subset : subsetArray) {
            Junctions junctions = fichotheque.getJunctions(subsetItem, subset);
            List<SubsetItem> subsetItemList = JunctionUtils.toSubsetItemList(junctions);
            for (SubsetItem otherSubsetItem : subsetItemList) {
                junctionEditor.removeJunction(otherSubsetItem, subsetItem);
            }
        }
    }

    public static void transferJunctions(FichothequeEditor fichothequeEditor, SubsetItem source, SubsetItem destination) {
        JunctionEditor junctionEditor = fichothequeEditor.getJunctionEditor();
        Fichotheque fichotheque = source.getFichotheque();
        List<SubsetItem> removeList = new ArrayList<SubsetItem>();
        Subset[] subsetArray = FichothequeUtils.toSubsetArray(fichotheque);
        JunctionChangeEngine junctionChangeEngine = JunctionChangeEngine.appendEngine(destination);
        for (Subset subset : subsetArray) {
            Junctions junctions = fichotheque.getJunctions(source, subset);
            List<Junctions.Entry> entryList = junctions.getEntryList();
            if (entryList.isEmpty()) {
                continue;
            }
            for (Junctions.Entry entry : entryList) {
                SubsetItem subsetItem = entry.getSubsetItem();
                for (Tie tie : entry.getJunction().getTieList()) {
                    junctionChangeEngine.addTie(subsetItem, tie.getMode(), tie.getWeight());
                }
                removeList.add(subsetItem);
            }
            for (SubsetItem subsetItem : removeList) {
                junctionEditor.removeJunction(source, subsetItem);
            }
            removeList.clear();
        }
        JunctionChanges junctionChanges = junctionChangeEngine.toJunctionChanges();
        for (JunctionChanges.Entry entry : junctionChanges.getEntryList()) {
            SubsetItem otherSubsetItem = entry.getSubsetItem();
            junctionEditor.updateJunction(destination, otherSubsetItem, entry.getJunctionChange());
        }
    }

    public static void copyJunctions(JunctionEditor junctionEditor, SubsetItem origin, SubsetItem destination, SubsetEligibility subsetEligibility) {
        Fichotheque fichotheque = origin.getFichotheque();
        Subset[] subsetArray = FichothequeUtils.toSubsetArray(fichotheque);
        JunctionChangeEngine junctionChangeEngine = JunctionChangeEngine.appendEngine(destination);
        for (Subset subset : subsetArray) {
            if (!subsetEligibility.accept(subset)) {
                continue;
            }
            junctionChangeEngine.addJunctions(fichotheque.getJunctions(origin, subset), subsetEligibility.getPredicate(subset));
        }
        junctionEditor.updateJunctions(destination, junctionChangeEngine.toJunctionChanges());
    }

    public static MetadataEditor getMetadataEditor(FichothequeEditor fichothequeEditor, Subset subset) {
        SubsetKey subsetKey = subset.getSubsetKey();
        switch (subsetKey.getCategory()) {
            case SubsetKey.CATEGORY_CORPUS:
                return fichothequeEditor.getCorpusEditor(subsetKey).getCorpusMetadataEditor();
            case SubsetKey.CATEGORY_THESAURUS:
                return fichothequeEditor.getThesaurusEditor(subsetKey).getThesaurusMetadataEditor();
            case SubsetKey.CATEGORY_SPHERE:
                return fichothequeEditor.getSphereEditor(subsetKey).getSphereMetadataEditor();
            case SubsetKey.CATEGORY_ALBUM:
                return fichothequeEditor.getAlbumEditor(subsetKey).getAlbumMetadataEditor();
            case SubsetKey.CATEGORY_ADDENDA:
                return fichothequeEditor.getAddendaEditor(subsetKey).getAddendaMetadataEditor();
            default:
                throw new SwitchException("Unknown category: " + subsetKey.getCategory());
        }
    }

    public static void copy(Metadata origin, MetadataEditor destinationEditor, String suffix) {
        for (Label label : origin.getTitleLabels()) {
            CleanedString cleanedString = CleanedString.newInstance(label.getLabelString() + suffix);
            destinationEditor.putTitle(LabelUtils.toLabel(label.getLang(), cleanedString));
        }
        for (Phrase phrase : origin.getPhrases()) {
            String name = phrase.getName();
            for (Label label : phrase) {
                CleanedString cleanedString = CleanedString.newInstance(label.getLabelString() + suffix);
                destinationEditor.putLabel(name, LabelUtils.toLabel(label.getLang(), cleanedString));
            }
        }
        for (Attribute attribute : origin.getAttributes()) {
            destinationEditor.putAttribute(attribute);
        }
    }

}
