/* BdfServer_Commands - Copyright (c) 2012-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.exportation;

import fr.exemole.bdfserver.api.BdfServer;
import fr.exemole.bdfserver.tools.instruction.BdfErrors;
import java.text.ParseException;
import java.util.List;
import java.util.Map;
import net.fichotheque.Subset;
import net.fichotheque.SubsetKey;
import net.fichotheque.corpus.Corpus;
import net.fichotheque.corpus.metadata.CorpusField;
import net.fichotheque.corpus.metadata.FieldKey;
import net.fichotheque.exportation.scrutari.CorpusScrutariDef;
import net.fichotheque.exportation.scrutari.ScrutariExportDef;
import net.fichotheque.exportation.scrutari.ThesaurusScrutariDef;
import net.fichotheque.format.FormatSourceKey;
import net.fichotheque.thesaurus.Thesaurus;
import net.fichotheque.tools.exportation.scrutari.CorpusScrutariDefBuilder;
import net.fichotheque.tools.exportation.scrutari.ScrutariExportDefBuilder;
import net.fichotheque.tools.exportation.scrutari.ScrutariExportUtils;
import net.fichotheque.tools.exportation.scrutari.ThesaurusScrutariDefBuilder;
import net.fichotheque.tools.exportation.scrutari.WrongFormatSourceKeyException;
import net.fichotheque.utils.CorpusMetadataUtils;
import net.mapeadores.util.localisation.Lang;
import net.mapeadores.util.localisation.Langs;
import net.mapeadores.util.localisation.LangsUtils;
import net.mapeadores.util.logging.ErrorMessageException;
import net.mapeadores.util.logging.LineLogs;
import net.mapeadores.util.request.RequestMap;
import net.mapeadores.util.text.AccoladePattern;
import net.mapeadores.util.text.CleanedString;
import net.mapeadores.util.text.LabelUtils;
import net.mapeadores.util.text.StringUtils;


/**
 *
 * @author Vincent Calame
 */
public class ScrutariExportChangeCommand extends AbstractDefChangeCommand {

    public final static String COMMANDNAME = "ScrutariExportChange";
    public final static String COMMANDKEY = "_ EXP-23";
    public final static String BASEICON_PARAMNAME = "baseicon";
    public final static String FICHEHREFPATTERN_PARAMNAME = "fichehrefpattern";
    public final static String MOTCLEHREFPATTERN_PARAMNAME = "motclehrefpattern";
    public final static String AUTHORITY_PARAMNAME = "authority";
    public final static String BASENAME_PARAMNAME = "basename";
    public final static String LANGSUI_PARAMNAME = "langsui";
    public final static String INCLUDETOKENS_PARAMSUFFIX = "|includetokens";
    public final static String FIELDGENERATIONSOURCE_PARAMSUFFIX = "|fieldgenerationsource";
    public final static String DATEKEY_PARAMSUFFIX = "|datekey";
    public final static String SELECTED_PARAMSUFFIX = "|selected";
    public final static String MULTILANG_PARAMSUFFIX = "|multilang";
    public final static String MULTILANGMODE_PARAMSUFFIX = "|multilangmode";
    public final static String THESAURUS_MULTILANG_PARAMSUFFIX = "|multilangthesaurus";
    public final static String FIELD_MULTILANG_PARAMSUFFIX = "|multilangfield";
    public final static String CUSTOM_MULTILANG_PARAMSUFFIX = "|multilangcustom";
    public final static String HREFPATTERN_PARAMSUFFIX = "|hrefpattern";
    public final static String WHOLETHESAURUS_PARAMSUFFIX = "|wholethesaurus";
    public final static String NONE_DATEKEY_PARAMVALUE = "none";
    public final static String SHORTBASEINTITULE_PARAMNAME = "shortbaseintitule";
    public final static String LONGBASEINTITULE_PARAMNAME = "longbaseintitule";
    private ScrutariExportDef scrutariExportDef;

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

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

    @Override
    protected void doCommand() {
        bdfServer.getScrutariExportManager().putScrutariExportDef(scrutariExportDef);
        putResultObject(SCRUTARIEXPORTDEF_OBJ, scrutariExportDef);
        Map<SubsetKey, LineLogs> lineLogsMap = ScrutariExportUtils.checkFieldGeneration(scrutariExportDef, bdfServer.getTableExportContext());
        if (!lineLogsMap.isEmpty()) {
            putResultObject(LINELOGSMAP_OBJ, lineLogsMap);
        }
        setDone("_ done.exportation.scrutariexportchange");
    }

    @Override
    protected void checkParameters() throws ErrorMessageException {
        checkFichothequeAdmin();
        ScrutariExportDef currentScrutariExportDef = requestHandler.getMandatoryScrutariExportDef();
        String authority = getMandatory(AUTHORITY_PARAMNAME);
        try {
            StringUtils.checkAuthority(authority);
        } catch (ParseException pe) {
            throw BdfErrors.error("_ error.wrong.authority", authority);
        }
        String baseName = getMandatory(BASENAME_PARAMNAME);
        try {
            StringUtils.checkTechnicalName(baseName, true);
        } catch (ParseException pe) {
            throw BdfErrors.error("_ error.wrong.basename", baseName);
        }
        String baseIcon = getMandatory(BASEICON_PARAMNAME);
        String includeTokens = requestHandler.getTrimedParameter("base" + INCLUDETOKENS_PARAMSUFFIX);
        ScrutariExportDefBuilder scrutariExportDefBuilder = ScrutariExportDefBuilder.init(currentScrutariExportDef.getName(), authority, baseName, currentScrutariExportDef.getAttributes())
                .setBaseIcon(baseIcon)
                .setFicheHrefPattern(getPattern(FICHEHREFPATTERN_PARAMNAME))
                .setMotcleHrefPattern(getPattern(MOTCLEHREFPATTERN_PARAMNAME))
                .setTargetName(getTargetName())
                .setTargetPath(getTargetPath())
                .parseIncludeTokens(includeTokens);
        String langsUi = getMandatory(LANGSUI_PARAMNAME);
        for (Lang lang : LangsUtils.toCleanLangArray(langsUi)) {
            scrutariExportDefBuilder.addLang(lang);
        }
        for (Corpus corpus : fichotheque.getCorpusList()) {
            CorpusScrutariDef corpusScrutariDef = getCorpusScrutariDef(corpus);
            if (corpusScrutariDef != null) {
                scrutariExportDefBuilder.addCorpusScrutariDef(corpusScrutariDef);
            }
        }
        for (Thesaurus thesaurus : fichotheque.getThesaurusList()) {
            ThesaurusScrutariDef thesaurusExportDef = getThesaurusExportDef(thesaurus);
            if (thesaurusExportDef != null) {
                scrutariExportDefBuilder.addThesaurusScrutariDef(thesaurusExportDef);
            }
        }
        String shortBaseIntitule = requestHandler.getTrimedParameter(SHORTBASEINTITULE_PARAMNAME);
        parseBaseIntitule(scrutariExportDefBuilder, 1, shortBaseIntitule);
        String longBaseIntitule = requestHandler.getTrimedParameter(LONGBASEINTITULE_PARAMNAME);
        parseBaseIntitule(scrutariExportDefBuilder, 2, longBaseIntitule);
        checkSelectionOptions(scrutariExportDefBuilder.getSelectionOptionsBuilder());
        checkDefBuilder(scrutariExportDefBuilder);
        this.scrutariExportDef = scrutariExportDefBuilder.toScrutariExportDef();
    }

    private void parseBaseIntitule(ScrutariExportDefBuilder scrutariExportBuilder, int baseIntituleType, String s) {
        String[] lines = StringUtils.getLineTokens(s, StringUtils.EMPTY_EXCLUDE);
        for (String line : lines) {
            int idx = line.indexOf("=");
            if (idx > 0) {
                try {
                    Lang langInteger = Lang.parse(line.substring(0, idx).trim());
                    CleanedString labelString = CleanedString.newInstance(line.substring(idx + 1));
                    if (labelString != null) {
                        scrutariExportBuilder.putBaseLabel(baseIntituleType, LabelUtils.toLabel(langInteger, labelString));
                    }
                } catch (ParseException lie) {

                }
            }
        }
    }

    private AccoladePattern getPattern(String paramName) throws ErrorMessageException {
        String patternParam = getMandatory(paramName);
        patternParam = patternParam.trim();
        if (patternParam.length() == 0) {
            return null;
        }
        try {
            AccoladePattern pattern = new AccoladePattern(patternParam);
            return pattern;
        } catch (java.text.ParseException pe) {
            return null;
        }
    }

    private CorpusScrutariDef getCorpusScrutariDef(Corpus corpus) throws ErrorMessageException {
        SubsetKey corpusKey = corpus.getSubsetKey();
        String corpusString = corpusKey.getKeyString();
        if (!requestHandler.isTrue(corpusString + SELECTED_PARAMSUFFIX)) {
            return null;
        }
        String dateKeyParam = getMandatory(corpusString + DATEKEY_PARAMSUFFIX);
        String fieldGenerationSource = getMandatory(corpusString + FIELDGENERATIONSOURCE_PARAMSUFFIX);
        String includeTokens = requestHandler.getTrimedParameter(corpusString + INCLUDETOKENS_PARAMSUFFIX);
        CorpusScrutariDefBuilder corpusScrutariDefBuilder = CorpusScrutariDefBuilder.init(corpusKey)
                .setFieldGenerationSource(fieldGenerationSource.trim())
                .parseIncludeTokens(includeTokens);
        FormatSourceKey dateFormatSourceKey = null;
        if (!(dateKeyParam.equals(NONE_DATEKEY_PARAMVALUE))) {
            try {
                dateFormatSourceKey = CorpusScrutariDefBuilder.parseDateKey(dateKeyParam);
            } catch (WrongFormatSourceKeyException | ParseException e) {
                throw BdfErrors.wrongParameterValue(corpusString + DATEKEY_PARAMSUFFIX, dateKeyParam);
            }
            if (dateFormatSourceKey.getSourceType().equals(FormatSourceKey.FIELDKEY_TYPE)) {
                FieldKey dateFieldKey = (FieldKey) dateFormatSourceKey.getKeyObject();
                List<CorpusField> corpusFieldList = CorpusMetadataUtils.getCorpusFieldListByFicheItemType(corpus.getCorpusMetadata(), CorpusField.DATE_FIELD, false);
                boolean present = false;
                for (CorpusField corpusField : corpusFieldList) {
                    if (corpusField.getFieldKey().equals(dateFieldKey)) {
                        present = true;
                        break;
                    }
                }
                if (!present) {
                    throw BdfErrors.wrongParameterValue(corpusString + DATEKEY_PARAMSUFFIX, dateKeyParam);
                }
            }
            corpusScrutariDefBuilder.setDateKey(dateFormatSourceKey);
        }
        if (requestHandler.isTrue(corpusString + MULTILANG_PARAMSUFFIX)) {
            String multilangMode = getMandatory(corpusString + MULTILANGMODE_PARAMSUFFIX);
            switch (multilangMode) {
                case CorpusScrutariDef.THESAURUS_MODE:
                    Subset thesaurus = requestHandler.getMandatorySubset(SubsetKey.CATEGORY_THESAURUS, corpusString + THESAURUS_MULTILANG_PARAMSUFFIX);
                    corpusScrutariDefBuilder.setThesaurusMode(thesaurus.getSubsetKey());
                    break;
                case CorpusScrutariDef.LANGUI_MODE:
                    corpusScrutariDefBuilder.setLanguiMode();
                    break;
                case CorpusScrutariDef.FIELD_MODE:
                    String fieldString = getMandatory(corpusString + FIELD_MULTILANG_PARAMSUFFIX);
                    try {
                        FieldKey fieldKey = FieldKey.parse(fieldString);
                        corpusScrutariDefBuilder.setFieldMode(fieldKey);
                    } catch (ParseException pe) {
                        throw BdfErrors.wrongParameterValue(corpusString + FIELD_MULTILANG_PARAMSUFFIX, fieldString);
                    }
                    break;
                case CorpusScrutariDef.CUSTOM_MODE:
                    String customString = getMandatory(corpusString + CUSTOM_MULTILANG_PARAMSUFFIX);
                    Langs langs = LangsUtils.toCleanLangs(customString);
                    corpusScrutariDefBuilder.setCustomMode(langs);
                    break;
            }
        }
        AccoladePattern hrefPattern = getPattern(corpusString + HREFPATTERN_PARAMSUFFIX);
        if (hrefPattern != null) {
            corpusScrutariDefBuilder.setHrefPattern(hrefPattern);
        }
        return corpusScrutariDefBuilder.toCorpusScrutariDef();
    }

    private ThesaurusScrutariDef getThesaurusExportDef(Thesaurus thesaurus) throws ErrorMessageException {
        SubsetKey thesaurusKey = thesaurus.getSubsetKey();
        if (!requestHandler.isTrue(thesaurusKey + SELECTED_PARAMSUFFIX)) {
            return null;
        }
        String fieldGenerationSource = getMandatory(thesaurusKey + FIELDGENERATIONSOURCE_PARAMSUFFIX);
        boolean wholeThesaurus = requestHandler.isTrue(thesaurusKey + WHOLETHESAURUS_PARAMSUFFIX);
        String includeTokens = requestHandler.getTrimedParameter(thesaurusKey + INCLUDETOKENS_PARAMSUFFIX);
        return ThesaurusScrutariDefBuilder.init(thesaurusKey)
                .setFieldGenerationSource(fieldGenerationSource)
                .setWholeThesaurus(wholeThesaurus)
                .parseIncludeTokens(includeTokens)
                .toThesaurusScrutariDef();
    }

}
