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

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.text.ParseException;
import net.fichotheque.corpus.Corpus;
import net.fichotheque.corpus.metadata.CorpusField;
import net.fichotheque.corpus.metadata.CorpusMetadata;
import net.fichotheque.corpus.metadata.CorpusMetadataEditor;
import net.fichotheque.corpus.metadata.ExistingFieldKeyException;
import net.fichotheque.corpus.metadata.FieldKey;
import net.fichotheque.corpus.metadata.FieldOptionConstants;
import net.fichotheque.corpus.metadata.FieldOptionException;
import net.mapeadores.util.exceptions.ShouldNotOccurException;
import net.mapeadores.util.exceptions.SwitchException;
import net.mapeadores.util.logging.ErrorMessageException;
import net.mapeadores.util.request.RequestMap;
import net.mapeadores.util.text.Label;
import net.mapeadores.util.text.LabelChange;


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

    public final static String COMMANDNAME = "FieldCreation";
    public final static String PROP_COMMANDKEY = "_ CRP-04";
    public final static String INFO_COMMANDKEY = "_ CRP-05";
    public final static String SECTION_COMMANDKEY = "_ CRP-06";
    public final static String CATEGORY_PARAMNAME = "category";
    public final static String NEWFIELDNAME_PARAMNAME = "newfieldname";
    public final static String FICHEITEMTYPE_PARAMNAME = "ficheitemtype";
    public final static String NEWLABEL_PARAMPREFIX = "newlabel/";
    private Corpus corpus;
    private FieldKey newFieldKey;
    private String ficheItemType = "";
    private LabelChange fieldLabelChange;

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

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

    @Override
    protected void doCommand() {
        try (EditSession session = startEditSession(Domains.CORPUS, COMMANDNAME)) {
            CorpusMetadataEditor corpusMetadataEditor = session.getFichothequeEditor().getCorpusEditor(corpus).getCorpusMetadataEditor();
            CorpusField corpusField;
            try {
                corpusField = corpusMetadataEditor.createCorpusField(newFieldKey, ficheItemType);
                setDefaultOptions(corpusMetadataEditor, corpusField);

            } catch (ExistingFieldKeyException efke) {
                throw new ShouldNotOccurException("test done before");
            }
            if (!fieldLabelChange.isEmpty()) {
                for (Label label : fieldLabelChange.getChangedLabels()) {
                    corpusMetadataEditor.putFieldLabel(corpusField, label);
                }
            }
        }
        putResultObject(CORPUS_OBJ, corpus);
        setDone("_ done.corpus.fieldcreation", newFieldKey.getKeyString());
    }

    @Override
    protected void checkParameters() throws ErrorMessageException {
        corpus = requestHandler.getMandatoryCorpus();
        checkSubsetAdmin(corpus);
        short category = checkCategory();
        String fieldNameParameter = getMandatory(NEWFIELDNAME_PARAMNAME);
        fieldNameParameter = fieldNameParameter.trim();
        if (fieldNameParameter.length() == 0) {
            throw BdfErrors.error("_ error.empty.fieldkey");
        }
        CorpusMetadata corpusMetadata = corpus.getCorpusMetadata();
        try {
            newFieldKey = FieldKey.parse(category, fieldNameParameter);
        } catch (ParseException pe) {
            throw BdfErrors.error("_ error.wrong.fieldkey", fieldNameParameter);
        }
        if (corpusMetadata.getCorpusField(newFieldKey) != null) {
            throw BdfErrors.error("_ error.existing.fieldkey", newFieldKey.getKeyString());
        }
        if (isWithTypeSelect(category)) {
            String ficheItemTypeParameter = getMandatory(FICHEITEMTYPE_PARAMNAME);
            if (ficheItemTypeParameter.length() == 0) {
                throw BdfErrors.error("_ error.empty.ficheitemtype", fieldNameParameter);
            }
            try {
                ficheItemType = CorpusField.checkFicheItemType(ficheItemTypeParameter);
            } catch (IllegalArgumentException iae) {
                throw BdfErrors.unknownParameterValue(FICHEITEMTYPE_PARAMNAME, ficheItemTypeParameter);
            }
        }
        fieldLabelChange = requestHandler.getLabelChange(NEWLABEL_PARAMPREFIX);
    }

    private short checkCategory() throws ErrorMessageException {
        String categoryParameter = getMandatory(CATEGORY_PARAMNAME);
        short category;
        try {
            category = FieldKey.categoryToShort(categoryParameter);
        } catch (IllegalArgumentException iae) {
            throw BdfErrors.unknownParameterValue(CATEGORY_PARAMNAME, categoryParameter);
        }
        switch (category) {
            case FieldKey.SPECIAL_CATEGORY:
                throw BdfErrors.unsupportedParameterValue(CATEGORY_PARAMNAME, categoryParameter);
            default:
                return category;
        }
    }

    public static String getCommandKey(short category) {
        switch (category) {
            case FieldKey.PROP_CATEGORY:
                return PROP_COMMANDKEY;
            case FieldKey.INFO_CATEGORY:
                return INFO_COMMANDKEY;
            case FieldKey.SECTION_CATEGORY:
                return SECTION_COMMANDKEY;

            default:
                throw new SwitchException("category = " + category);
        }
    }

    public static boolean isWithTypeSelect(short category) {
        switch (category) {
            case FieldKey.PROP_CATEGORY:
            case FieldKey.INFO_CATEGORY:
                return true;
            default:
                return false;
        }
    }


    private void setDefaultOptions(CorpusMetadataEditor corpusMetadataEditor, CorpusField corpusField) {
        if (corpusField.isProp()) {
            switch (corpusField.getFicheItemType()) {
                case CorpusField.PERSON_FIELD:
                case CorpusField.GEOPOINT_FIELD:
                    try {
                    corpusMetadataEditor.setFieldOption(corpusField, FieldOptionConstants.SUBFIELDDISPLAY_OPTION, "1");
                } catch (FieldOptionException foe) {
                    throw new ShouldNotOccurException(foe);
                }
                break;
            }
        } else if (corpusField.isInfo()) {
            switch (corpusField.getFicheItemType()) {
                case CorpusField.AMOUNT_FIELD:
                case CorpusField.PARA_FIELD:
                    try {
                    corpusMetadataEditor.setFieldOption(corpusField, FieldOptionConstants.INFODISPLAY_OPTION, FieldOptionConstants.BLOCK_DISPLAY);
                } catch (FieldOptionException foe) {
                    throw new ShouldNotOccurException(foe);
                }
                break;
            }
        }

    }

}
