/* 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.thesaurus;

import java.text.ParseException;
import java.util.List;
import net.fichotheque.ExistingIdException;
import net.fichotheque.FichothequeEditor;
import net.fichotheque.thesaurus.Motcle;
import net.fichotheque.thesaurus.ParentRecursivityException;
import net.fichotheque.thesaurus.Thesaurus;
import net.fichotheque.thesaurus.ThesaurusEditor;
import net.fichotheque.thesaurus.metadata.ThesaurusMetadata;
import net.fichotheque.tools.FichothequeTools;
import net.mapeadores.util.attr.Attribute;
import net.mapeadores.util.exceptions.ImplementationException;
import net.mapeadores.util.exceptions.ShouldNotOccurException;
import net.mapeadores.util.localisation.Lang;
import net.mapeadores.util.localisation.Langs;
import net.mapeadores.util.text.Label;


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

    private ThesaurusTools() {
    }

    /**
     * Transfère l'indexation d'un mot-clé vers un autre mot-clé.
     *
     * @throws ParentRecursivityException si la destination est un mot-clé fils
     * de la source
     * @throws IllegalArgumentException si les mots-clés ne sont pas du même
     * thésaurus
     */
    public static void transferChildren(FichothequeEditor fichothequeEditor, Motcle source, Motcle destination) throws ParentRecursivityException {
        List<Motcle> childList = source.getChildList();
        if (childList.isEmpty()) {
            return;
        }
        Thesaurus thesaurus = source.getThesaurus();
        if (destination != null) {
            if (!destination.getThesaurus().equals(thesaurus)) {
                throw new IllegalArgumentException("source and destination are not coming from the same thesaurus");
            }
            if (destination.isDescendantOf(source)) {
                throw new ParentRecursivityException(destination, source);
            }
        }
        ThesaurusEditor thesaurusEditor = fichothequeEditor.getThesaurusEditor(thesaurus);
        for (Motcle child : childList) {
            try {
                thesaurusEditor.setParent(child, destination);
            } catch (ParentRecursivityException pre) {
                throw new ImplementationException("recursivity has been checked before in the script", pre);
            }
        }
    }

    public static void transferLabels(FichothequeEditor fichothequeEditor, Motcle source, Motcle destination, Langs langs) {
        if (langs == null) {
            return;
        }
        Thesaurus thesaurus = destination.getThesaurus();
        if (thesaurus.isBabelienType()) {
            return;
        }
        ThesaurusEditor thesaurusEditor = fichothequeEditor.getThesaurusEditor(thesaurus);
        ThesaurusMetadata metadata = thesaurus.getThesaurusMetadata();
        int langSize = langs.size();
        for (Label label : source.getLabels()) {
            Lang lang = label.getLang();
            boolean accepte = false;
            for (int i = 0; i < langSize; i++) {
                if (langs.get(i).equals(lang)) {
                    accepte = true;
                    break;
                }
            }
            if (accepte) {
                Label current = destination.getLabels().getLabel(lang);
                if (current == null) {
                    thesaurusEditor.putLabel(destination, label);
                }
            }
        }
    }

    /**
     * Transfère l'indexation d'un mot-clé vers un autre mot-clé.
     *
     */

    public static void merge(FichothequeEditor fichothequeEditor, Motcle source, Motcle destination, Langs langs) throws ParentRecursivityException {
        if (source.getThesaurus().equals(destination.getThesaurus())) {
            transferChildren(fichothequeEditor, source, destination);
        } else {
            try {
                transferChildren(fichothequeEditor, source, source.getParent());
            } catch (ParentRecursivityException pre) {
                throw new ImplementationException("recursivity has been checked before in the script", pre);
            }
        }
        FichothequeTools.transferJunctions(fichothequeEditor, source, destination);
        if (langs != null) {
            transferLabels(fichothequeEditor, source, destination, langs);
        }
        fichothequeEditor.getThesaurusEditor(source.getSubsetKey()).removeMotcle(source);
    }

    /**
     *
     * @throws IllegalArgumentException si le thésaurus de destination est celui
     * du mot-clé
     */
    public static Motcle move(FichothequeEditor fichothequeEditor, Motcle source, Thesaurus destination, Langs langs) {
        if (source.getThesaurus().equals(destination)) {
            throw new IllegalArgumentException("source.getThesaurus().equals(destination)");
        }
        ThesaurusEditor destinationEditor = fichothequeEditor.getThesaurusEditor(destination.getSubsetKey());
        Motcle copy = copy(fichothequeEditor, destinationEditor, source);
        try {
            merge(fichothequeEditor, source, copy, langs);
        } catch (ParentRecursivityException pre) {
            throw new ImplementationException("recursivity has been checked before in the script", pre);
        }
        return copy;
    }

    public static Motcle copy(FichothequeEditor fichothequeEditor, ThesaurusEditor thesaurusEditor, Motcle source) {
        String idalpha = source.getIdalpha();
        Thesaurus destinationThesaurus = thesaurusEditor.getThesaurus();
        if (destinationThesaurus.isIdalphaType()) {
            if (idalpha != null) {
                if (destinationThesaurus.getMotcleByIdalpha(idalpha) != null) {
                    idalpha = null;
                }
            }
            if (idalpha == null) {
                idalpha = "n_" + String.valueOf(source.getId());
                if (destinationThesaurus.getMotcleByIdalpha(idalpha) != null) {
                    int p = 1;
                    while (true) {
                        String test = idalpha + "-" + p;
                        if (destinationThesaurus.getMotcleByIdalpha(test) == null) {
                            idalpha = test;
                            break;
                        }
                        p++;
                    }
                }
            }
        } else {
            idalpha = null;
        }
        try {
            Motcle destination = thesaurusEditor.createMotcle(-1, idalpha);
            copy(thesaurusEditor, source, destination);
            return destination;
        } catch (ExistingIdException | ParseException e) {
            throw new ShouldNotOccurException(e);
        }
    }

    public static void copy(ThesaurusEditor thesaurusEditor, Motcle origin, Motcle destination) {
        for (Label label : origin.getLabels()) {
            thesaurusEditor.putLabel(destination, label);
        }
        FichothequeEditor fichothequeEditor = thesaurusEditor.getFichothequeEditor();
        for (Attribute attribute : origin.getAttributes()) {
            fichothequeEditor.putAttribute(destination, attribute);
        }
    }

}
