/* BdfServer - Copyright (c) 2023-2024 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.tools.overview;

import fr.exemole.bdfserver.api.EditSession;
import fr.exemole.bdfserver.api.ui.FieldUi;
import fr.exemole.bdfserver.api.ui.UiComponents;
import fr.exemole.bdfserver.tools.ui.components.FieldUiBuilder;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
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.fichotheque.utils.FieldOptionUtils;
import net.mapeadores.util.attr.AttributeChangeBuilder;
import net.mapeadores.util.exceptions.ShouldNotOccurException;
import net.mapeadores.util.localisation.Lang;
import net.mapeadores.util.logging.LineMessageException;
import net.mapeadores.util.text.LabelChangeBuilder;


/**
 *
 * @author Vincent Calame
 */
class FieldBlock extends OverviewBlock {

    private final CorpusMetadata corpusMetadata;
    private final FieldKey fieldKey;
    private final FieldUiBuilder builder;
    private final LabelChangeBuilder labelChangeBuilder = new LabelChangeBuilder();
    private final String ficheItemType;
    private final Map<String, Object> optionMap = new HashMap<String, Object>();
    private CorpusField corpusField;

    FieldBlock(int lineNumber, FieldUi fieldUi, CorpusMetadata corpusMetadata) {
        super(lineNumber, fieldUi);
        builder = FieldUiBuilder.derive(fieldUi);
        this.fieldKey = fieldUi.getFieldKey();
        this.corpusMetadata = corpusMetadata;
        this.ficheItemType = corpusMetadata.getCorpusField(fieldKey).getFicheItemType();
    }

    FieldBlock(int lineNumber, FieldKey fieldKey, String ficheItemType, CorpusMetadata corpusMetadata) {
        super(lineNumber, fieldKey.getKeyString());
        builder = new FieldUiBuilder(fieldKey);
        this.fieldKey = fieldKey;
        this.corpusMetadata = corpusMetadata;
        this.ficheItemType = ficheItemType;
    }

    @Override
    public boolean addText(String name, Lang lang, String text) {
        if (!isValidText(name)) {
            return false;
        }
        labelChangeBuilder.putLabel(lang, text);
        return true;
    }

    private boolean isValidText(String labelName) {
        switch (labelName) {
            case "label":
                return true;
            default:
                return false;
        }
    }

    @Override
    public void put(int lineNumber, String key, String value) throws LineMessageException {
        switch (key) {
            case "status":
                if (!FieldUi.isModifiableStatus(fieldKey)) {
                    throw new LineMessageException(lineNumber, OverviewEngine.SEVERE_FICHOTHEQUE, "_ error.unknown.conf.key", key);
                }
                String status = checkStatus(lineNumber, value);
                builder.setStatus(status);
                break;
            case "type":
                break;
            default:
                throw new LineMessageException(lineNumber, OverviewEngine.SEVERE_FICHOTHEQUE, "_ error.unknown.conf.key", key);
        }
    }

    @Override
    public void put(int lineNumber, String key, String name, String value) throws LineMessageException {
        switch (key) {
            case "field": {
                try {
                    name = FieldOptionConstants.checkAlias(name);
                    FieldOptionUtils.checkUsage(name, fieldKey, ficheItemType);
                } catch (FieldOptionException foe) {
                    throw new LineMessageException(lineNumber, OverviewEngine.SEVERE_FICHOTHEQUE, "_ error.unknown.conf.keyparam", name);
                }
                try {
                    Object optionObject = FieldOptionUtils.parseOptionValue(name, value);
                    optionMap.put(name, optionObject);
                } catch (FieldOptionException foe) {
                    throw new LineMessageException(lineNumber, OverviewEngine.SEVERE_FICHOTHEQUE, "_ error.wrong.parametervalue", name, value);
                }
                break;
            }
            case "ui": {
                Object uiOptionObject = parseOptionValue(name, value);
                if (uiOptionObject != null) {
                    builder.putOption(name, uiOptionObject);
                }
                break;
            }
            default:
                throw new LineMessageException(lineNumber, OverviewEngine.SEVERE_FICHOTHEQUE, "_ error.unknown.conf.key", key);
        }
    }

    @Override
    public AttributeChangeBuilder getAttributeChangeBuilder() {
        return builder.getAttributeChangeBuilder();
    }

    @Override
    public void firstPass(EditSession editSession, UiComponents uiComponents) {
        CorpusMetadataEditor corpusMetadataEditor = editSession.getFichothequeEditor().getCorpusEditor(corpusMetadata.getCorpus()).getCorpusMetadataEditor();
        corpusField = corpusMetadata.getCorpusField(fieldKey);
        if (corpusField == null) {
            try {
                corpusField = corpusMetadataEditor.createCorpusField(fieldKey, ficheItemType);
            } catch (ExistingFieldKeyException iee) {
                throw new ShouldNotOccurException("test done before");
            }
        }
        corpusMetadataEditor.changeFieldLabels(corpusField, labelChangeBuilder.toLabelChange());
        editSession.getBdfServerEditor().putComponentUi(uiComponents, builder.toFieldUi());
    }

    @Override
    public void secondPass(EditSession editSession, UiComponents uiComponents) {
        CorpusMetadataEditor corpusMetadataEditor = editSession.getFichothequeEditor().getCorpusEditor(corpusMetadata.getCorpus()).getCorpusMetadataEditor();
        for (Entry<String, Object> entry : optionMap.entrySet()) {
            try {
                corpusMetadataEditor.setFieldOption(corpusField, entry.getKey(), entry.getValue());
            } catch (FieldOptionException foe) {

            }
        }
    }

}
