/* BdfServer_Commands - Copyright (c) 2010-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 fr.exemole.bdfserver.commands.thesaurus;

import fr.exemole.bdfserver.api.BdfServer;
import fr.exemole.bdfserver.api.EditSession;
import fr.exemole.bdfserver.api.interaction.Domains;
import fr.exemole.bdfserver.tools.instruction.AbstractBdfCommand;
import fr.exemole.bdfserver.tools.instruction.BdfErrors;
import java.util.ArrayList;
import java.util.List;
import net.fichotheque.corpus.Corpus;
import net.fichotheque.corpus.FicheMeta;
import net.fichotheque.croisement.CroisementChanges;
import net.fichotheque.croisement.CroisementEditor;
import net.fichotheque.thesaurus.Motcle;
import net.fichotheque.tools.croisement.CroisementChangeEngine;
import net.fichotheque.tools.croisement.LienBuffer;
import net.mapeadores.util.logging.ErrorMessageException;
import net.mapeadores.util.request.RequestMap;


/**
 *
 * @author Vincent Calame
 */
public class SelectionIndexationCommand extends AbstractBdfCommand {

    public final static String COMMANDNAME = "SelectionIndexation";
    public final static String COMMANDKEY = "_ THS-22";
    public final static String ADD_PARAMSUFFIX = "ajout_";
    public final static String REMOVE_PARAMSUFFIX = "supp_";
    public final static String WEIGHT_PARAMSUFFIX = "weight_";
    private Motcle motcle;
    private List<CorpusInfo> corpusInfoList;
    private String mode;

    public SelectionIndexationCommand(BdfServer bdfServer, RequestMap requestMap) {
        super(bdfServer, requestMap);
    }

    @Override
    public boolean needSynchronisation() {
        return true;
    }

    @Override
    protected void doCommand() throws ErrorMessageException {
        int[] countArray;
        try (EditSession session = startEditSession(Domains.THESAURUS, COMMANDNAME)) {
            CroisementEditor croisementEditor = session.getFichothequeEditor().getCroisementEditor();
            CroisementChangeEngine croisementChangeEngine = CroisementChangeEngine.appendOrWeightReplaceEngine(motcle);
            for (CorpusInfo corpusInfo : corpusInfoList) {
                corpusInfo.run(croisementChangeEngine);
            }
            CroisementChanges croisementChanges = croisementChangeEngine.toCroisementChanges();
            croisementEditor.updateCroisements(motcle, croisementChanges);
            countArray = getCount(croisementChanges);
        }
        putResultObject(INTARRAY_OBJ, countArray);
        putResultObject(MOTCLE_OBJ, motcle);
        setDone("_ done.edition.selectionindexation");
    }

    @Override
    protected void checkParameters() throws ErrorMessageException {
        motcle = requestHandler.getMandatoryMotcle();
        mode = requestHandler.getMode();
        checkSubsetAdmin(motcle.getThesaurus());
        corpusInfoList = new ArrayList<CorpusInfo>();
        for (Corpus corpus : fichotheque.getCorpusList()) {
            List<FicheMeta> removeList = getRemoveList(corpus);
            List<LienBuffer> addList = getAddList(corpus, mode);
            if ((removeList != null) || (addList != null)) {
                corpusInfoList.add(new CorpusInfo(corpus, addList, removeList, mode));
            }
        }
        if (corpusInfoList.isEmpty()) {
            throw BdfErrors.error("_ error.empty.selectionindexation");
        }
    }

    private List<LienBuffer> getAddList(Corpus corpus, String mode) throws ErrorMessageException {
        String[] addValues = requestHandler.getTokens(ADD_PARAMSUFFIX + corpus.getSubsetName());
        if (addValues.length == 0) {
            return null;
        }
        List<LienBuffer> lienBufferList = new ArrayList<LienBuffer>();
        for (String value : addValues) {
            try {
                int id = Integer.parseInt(value);
                FicheMeta ficheMeta = corpus.getFicheMetaById(id);
                if (ficheMeta != null) {
                    lienBufferList.add(new LienBuffer(ficheMeta, mode, getWeight(ficheMeta)));
                }
            } catch (NumberFormatException nfe) {
            }
        }
        if (lienBufferList.isEmpty()) {
            return null;
        }
        return lienBufferList;
    }

    private List<FicheMeta> getRemoveList(Corpus corpus) throws ErrorMessageException {
        String[] removeValues = requestHandler.getTokens(REMOVE_PARAMSUFFIX + corpus.getSubsetName());
        if (removeValues.length == 0) {
            return null;
        }
        List<FicheMeta> removeList = new ArrayList<FicheMeta>();
        for (String value : removeValues) {
            try {
                int id = Integer.parseInt(value);
                FicheMeta ficheMeta = corpus.getFicheMetaById(id);
                if (ficheMeta != null) {
                    removeList.add(ficheMeta);
                }
            } catch (NumberFormatException nfe) {
            }
        }
        if (removeList.isEmpty()) {
            return null;
        }
        return removeList;
    }

    private int getWeight(FicheMeta ficheMeta) throws ErrorMessageException {
        String param = requestHandler.getTrimedParameter(WEIGHT_PARAMSUFFIX + ficheMeta.getSubsetName() + "_" + String.valueOf(ficheMeta.getId()));
        if (param.isEmpty()) {
            return 1;
        }
        try {
            int weight = Integer.parseInt(param);
            if (weight < 1) {
                weight = 1;
            }
            return weight;
        } catch (NumberFormatException nfe) {
            return 1;
        }
    }

    private int[] getCount(CroisementChanges croisementChanges) {
        int addCount = 0;
        int removeCount = 0;
        for (CroisementChanges.Entry entry : croisementChanges.getEntryList()) {
            if (entry.getCroisementChange().getChangedLienList().isEmpty()) {
                removeCount++;
            } else {
                addCount++;
            }
        }
        int[] result = {addCount, removeCount};
        return result;
    }

    public static String getAddParamName(String corpusName) {
        return ADD_PARAMSUFFIX + corpusName;
    }

    public static String getWeightParamName(String corpusName, String ficheId) {
        return WEIGHT_PARAMSUFFIX + corpusName + "_" + ficheId;
    }

    public static String getRemoveParamName(String corpusName) {
        return REMOVE_PARAMSUFFIX + corpusName;
    }


    private static class CorpusInfo {

        private final Corpus corpus;
        private final List<LienBuffer> addList;
        private final List<FicheMeta> removeList;
        private final String mode;

        private CorpusInfo(Corpus corpus, List<LienBuffer> addList, List<FicheMeta> removeList, String mode) {
            this.corpus = corpus;
            this.addList = addList;
            this.removeList = removeList;
            this.mode = mode;
        }

        private void run(CroisementChangeEngine croisementChangeEngine) {
            if (addList != null) {
                for (LienBuffer lienBuffer : addList) {
                    croisementChangeEngine.addLien(lienBuffer);
                }
            }
            if (removeList != null) {
                for (FicheMeta ficheMeta : removeList) {
                    croisementChangeEngine.removeLien(ficheMeta, mode);
                }
            }
        }

    }

}
