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

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.croisement.CroisementChanges;
import net.fichotheque.croisement.CroisementEditor;
import net.fichotheque.croisement.Croisements;
import net.fichotheque.croisement.Lien;
import net.fichotheque.eligibility.SubsetEligibility;
import net.fichotheque.thesaurus.Motcle;
import net.fichotheque.thesaurus.ParentRecursivityException;
import net.fichotheque.thesaurus.Thesaurus;
import net.fichotheque.tools.croisement.CroisementChangeEngine;
import net.fichotheque.tools.thesaurus.ThesaurusTools;
import net.fichotheque.utils.CroisementUtils;
import net.fichotheque.utils.FichothequeUtils;
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();
        removeCroisements(fichothequeEditor, ficheMeta);
        int ficheid = ficheMeta.getId();
        for (Corpus satelliteCorpus : corpus.getSatelliteCorpusList()) {
            FicheMeta satelliteFicheMeta = satelliteCorpus.getFicheMetaById(ficheid);
            if (satelliteFicheMeta != null) {
                removeCroisements(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();
        removeCroisements(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) {
        removeCroisements(fichothequeEditor, document);
        AddendaEditor addendaEditor = fichothequeEditor.getAddendaEditor(document.getAddenda());
        return addendaEditor.removeDocument(document);
    }

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

    private static void removeCroisements(FichothequeEditor fichothequeEditor, SubsetItem subsetItem) {
        CroisementEditor croisementEditor = fichothequeEditor.getCroisementEditor();
        Fichotheque fichotheque = subsetItem.getFichotheque();
        Subset[] subsetArray = FichothequeUtils.toSubsetArray(fichotheque);
        for (Subset subset : subsetArray) {
            Croisements croisements = fichotheque.getCroisements(subsetItem, subset);
            List<SubsetItem> subsetItemList = CroisementUtils.toSubsetItemList(croisements);
            for (SubsetItem otherSubsetItem : subsetItemList) {
                croisementEditor.removeCroisement(otherSubsetItem, subsetItem);
            }
        }
    }

    public static void transferCroisements(FichothequeEditor fichothequeEditor, SubsetItem source, SubsetItem destination) {
        CroisementEditor croisementEditor = fichothequeEditor.getCroisementEditor();
        Fichotheque fichotheque = source.getFichotheque();
        List<SubsetItem> removeList = new ArrayList<SubsetItem>();
        Subset[] subsetArray = FichothequeUtils.toSubsetArray(fichotheque);
        CroisementChangeEngine croisementChangeEngine = CroisementChangeEngine.appendEngine(destination);
        for (Subset subset : subsetArray) {
            Croisements croisements = fichotheque.getCroisements(source, subset);
            List<Croisements.Entry> entryList = croisements.getEntryList();
            if (entryList.isEmpty()) {
                continue;
            }
            for (Croisements.Entry entry : entryList) {
                SubsetItem subsetItem = entry.getSubsetItem();
                for (Lien lien : entry.getCroisement().getLienList()) {
                    croisementChangeEngine.addLien(subsetItem, lien.getMode(), lien.getWeight());
                }
                removeList.add(subsetItem);
            }
            for (SubsetItem subsetItem : removeList) {
                croisementEditor.removeCroisement(source, subsetItem);
            }
            removeList.clear();
        }
        CroisementChanges croisementChanges = croisementChangeEngine.toCroisementChanges();
        for (CroisementChanges.Entry entry : croisementChanges.getEntryList()) {
            SubsetItem otherSubsetItem = entry.getSubsetItem();
            croisementEditor.updateCroisement(destination, otherSubsetItem, entry.getCroisementChange());
        }
    }

    public static void copyCroisements(CroisementEditor croisementEditor, SubsetItem origin, SubsetItem destination, SubsetEligibility subsetEligibility) {
        Fichotheque fichotheque = origin.getFichotheque();
        Subset[] subsetArray = FichothequeUtils.toSubsetArray(fichotheque);
        CroisementChangeEngine croisementChangeEngine = CroisementChangeEngine.appendEngine(destination);
        for (Subset subset : subsetArray) {
            if (!subsetEligibility.accept(subset)) {
                continue;
            }
            croisementChangeEngine.addCroisements(fichotheque.getCroisements(origin, subset), subsetEligibility.getPredicate(subset));
        }
        croisementEditor.updateCroisements(destination, croisementChangeEngine.toCroisementChanges());
    }

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

}
