/* BdfServer_Commands - 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 fr.exemole.bdfserver.commands.importation;

import fr.exemole.bdfserver.api.BdfServer;
import fr.exemole.bdfserver.api.ui.IncludeUi;
import fr.exemole.bdfserver.api.ui.UiComponents;
import fr.exemole.bdfserver.tools.importation.ImportationEngine;
import fr.exemole.bdfserver.tools.importation.ImportationFileUtils;
import fr.exemole.bdfserver.tools.instruction.AbstractBdfCommand;
import fr.exemole.bdfserver.tools.instruction.BdfErrors;
import java.io.File;
import java.io.IOException;
import java.text.ParseException;
import net.fichotheque.Metadata;
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.importation.LabelImport;
import net.fichotheque.importation.ParseResult;
import net.fichotheque.include.IncludeKey;
import net.fichotheque.tools.importation.LabelImportBuilder;
import net.fichotheque.tools.importation.ParseResultBuilder;
import net.mapeadores.util.localisation.Lang;
import net.mapeadores.util.logging.ErrorMessageException;
import net.mapeadores.util.logging.LineMessageHandler;
import net.mapeadores.util.request.RequestMap;
import net.mapeadores.util.text.CleanedString;
import net.mapeadores.util.text.Label;
import net.mapeadores.util.text.Labels;
import net.mapeadores.util.text.StringUtils;
import net.mapeadores.util.text.coupleparser.Couple;
import net.mapeadores.util.text.coupleparser.CoupleParser;
import net.mapeadores.util.text.coupleparser.ErrorCouple;
import net.mapeadores.util.text.coupleparser.IdalphaCouple;


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

    public final static String COMMANDNAME = "LabelImportParse";
    public final static String COMMANDKEY = "_ IMP-03";
    public final static String CONTENT_PARAMNAME = "content";
    public final static String LANG_PARAMNAME = "lang";
    public final static String SEPARATOR_PARAMNAME = "separator";
    private String content;
    private char separator = '\n';
    private Lang lang;

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

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

    @Override
    protected void doCommand() throws ErrorMessageException {
        ParseResultBuilder parseResultBuilder = new ParseResultBuilder(ImportationEngine.LABEL_IMPORT);
        LabelImport labelImport = parse(parseResultBuilder, content, separator);
        try {
            File tmpFile = ImportationFileUtils.saveTmpXml(bdfServer, labelImport);
            parseResultBuilder.setPath(tmpFile.getName());
        } catch (IOException ioe) {
            throw BdfErrors.ioException(ioe);
        }
        putResultObject(PARSERESULT_OBJ, parseResultBuilder.toParseResult());
    }

    @Override
    protected void checkParameters() throws ErrorMessageException {
        checkFichothequeAdmin();
        this.content = getMandatory(CONTENT_PARAMNAME);
        String langString = getMandatory(LANG_PARAMNAME);
        try {
            this.lang = Lang.parse(langString);
        } catch (ParseException pe) {
            throw BdfErrors.wrongParameterValue(LANG_PARAMNAME, langString);
        }
        String separatorValue = requestHandler.getTrimedParameter(SEPARATOR_PARAMNAME);
        if (!separatorValue.isEmpty()) {
            try {
                separator = StringUtils.stringToChar(separatorValue);
            } catch (IllegalArgumentException iae) {
                throw BdfErrors.wrongParameterValue(SEPARATOR_PARAMNAME, separatorValue);
            }
        }
    }

    private LabelImport parse(ParseResultBuilder parseResultBuilder, String content, char separator) {
        LineMessageHandler lineMessageHandler = parseResultBuilder.getLineMessageHandler();
        LabelImportBuilder labelImportBuilder = new LabelImportBuilder(lang);
        CoupleParser coupleParser = new CoupleParser(CoupleParser.IDALPHA_MODE);
        coupleParser.setSeparator(separator);
        Couple[] coupleArray = coupleParser.parse(content);
        int length = coupleArray.length;
        for (int i = 0; i < length; i++) {
            Couple couple = coupleArray[i];
            if (couple instanceof ErrorCouple) {
                lineMessageHandler.addMessage(ParseResult.SEVERE_PARSE, couple.getLineNumber(), "_ error.wrong.tableimport.line", couple.getValue());
            } else {
                IdalphaCouple idalphaCouple = (IdalphaCouple) couple;
                CleanedString value = CleanedString.newInstance(couple.getValue());
                String idalpha = idalphaCouple.getIdalpha();
                int lineNumber = couple.getLineNumber();
                boolean doublon = parseResultBuilder.checkDoublon(idalpha, lineNumber);
                if (!doublon) {
                    int idx = idalpha.indexOf('/');
                    if (idx < 0) {
                        lineMessageHandler.addMessage(ParseResult.SEVERE_PARSE, lineNumber, "_ error.wrong.idalpha", idalpha);
                    } else {
                        String part1 = idalpha.substring(0, idx);
                        String part2 = idalpha.substring(idx + 1);
                        if (part1.length() == 0) {
                            lineMessageHandler.addMessage(ParseResult.SEVERE_PARSE, lineNumber, "_ error.empty.tableimport.firstkeypart", idalpha);
                        } else if (part2.length() == 0) {
                            lineMessageHandler.addMessage(ParseResult.SEVERE_PARSE, lineNumber, "_ error.empty.tableimport.secondkeypart", idalpha);
                        }
                        if (part1.equals("fichotheque")) {
                            parseFichothequeMetadata(fichotheque.getFichothequeMetadata(), parseResultBuilder, labelImportBuilder, idalpha, lineNumber, part2, value);
                        } else {
                            try {
                                SubsetKey subsetKey = SubsetKey.parse(part1);
                                Subset subset = fichotheque.getSubset(subsetKey);
                                if (subset == null) {
                                    lineMessageHandler.addMessage(ParseResult.SEVERE_FICHOTHEQUE, lineNumber, "_ error.unknown.subset", idalpha);
                                } else if (subset instanceof Corpus) {
                                    parseCorpus((Corpus) subset, parseResultBuilder, labelImportBuilder, idalpha, lineNumber, part2, value);
                                } else {
                                    parseSubsetMetadata(subset, parseResultBuilder, labelImportBuilder, idalpha, lineNumber, part2, value);
                                }
                            } catch (java.text.ParseException pe) {
                                lineMessageHandler.addMessage(ParseResult.SEVERE_FICHOTHEQUE, lineNumber, "_ error.unknown.tableimport.firstkeypart", idalpha);
                            }
                        }
                    }
                }
            }
        }
        return labelImportBuilder.toLabelImport();
    }

    private void parseFichothequeMetadata(Metadata fichothequeMetadata, ParseResultBuilder parseResultBuilder, LabelImportBuilder labelImportBuilder, String idString, int lineNumber, String part2, CleanedString value) {
        LineMessageHandler lineMessageHandler = parseResultBuilder.getLineMessageHandler();
        String phraseName;
        if (part2.equals("title")) {
            labelImportBuilder.addFichothequePhrase(null, value);
            String[] array = getValueArray(fichothequeMetadata.getTitleLabels(), value);
            parseResultBuilder.addResult(idString, idString, array, lineNumber);
        } else {
            phraseName = toPhraseName(part2);
            if (phraseName == null) {
                lineMessageHandler.addMessage(ParseResult.SEVERE_PARSE, lineNumber, "_ error.wrong.phrasename", idString);
            } else {
                labelImportBuilder.addFichothequePhrase(phraseName, value);
                String[] array = getValueArray(fichothequeMetadata.getPhrases().getPhrase(phraseName), value);
                parseResultBuilder.addResult(idString, idString, array, lineNumber);
            }
        }
    }

    private void parseCorpus(Corpus corpus, ParseResultBuilder parseResultBuilder, LabelImportBuilder labelImportBuilder, String idString, int lineNumber, String part2, CleanedString value) {
        LineMessageHandler lineMessageHandler = parseResultBuilder.getLineMessageHandler();
        if (!parseSubsetMetadata(corpus, parseResultBuilder, labelImportBuilder, idString, lineNumber, part2, value)) {
            try {
                FieldKey fieldKey = FieldKey.parse(part2);
                CorpusField corpusField = corpus.getCorpusMetadata().getCorpusField(fieldKey);
                if (corpusField == null) {
                    lineMessageHandler.addMessage(ParseResult.SEVERE_FICHOTHEQUE, lineNumber, "_ error.unknown.fieldkey", idString);
                } else {
                    labelImportBuilder.addFieldKeyImport(corpus, fieldKey, value);
                    String[] array = getValueArray(corpusField, value);
                    parseResultBuilder.addResult(idString, idString, array, lineNumber);
                }
            } catch (ParseException pe) {
                try {
                    IncludeKey includeKey = IncludeKey.parse(part2);
                    labelImportBuilder.addIncludeKeyImport(corpus, includeKey, value);
                    String[] array = getValueArray(corpus, includeKey, value);
                    parseResultBuilder.addResult(idString, idString, array, lineNumber);
                } catch (ParseException pe2) {
                    lineMessageHandler.addMessage(ParseResult.SEVERE_FICHOTHEQUE, lineNumber, "_ error.unknown.key", idString);
                }
            }
        }
    }

    private boolean parseSubsetMetadata(Subset subset, ParseResultBuilder parseResultBuilder, LabelImportBuilder labelImportBuilder, String idString, int lineNumber, String part2, CleanedString value) {
        LineMessageHandler lineMessageHandler = parseResultBuilder.getLineMessageHandler();
        String phraseName;
        if (part2.equals("title")) {
            labelImportBuilder.addSubsetPhrase(subset, null, value);
            String[] array = getValueArray(subset.getMetadata().getTitleLabels(), value);
            parseResultBuilder.addResult(idString, idString, array, lineNumber);
            return true;
        } else {
            phraseName = toPhraseName(part2);
            if (phraseName == null) {
                if (!subset.getSubsetKey().isCorpusSubset()) {
                    lineMessageHandler.addMessage("_ error.wrong.phrasename", lineNumber, idString);
                }
                return false;
            } else {
                labelImportBuilder.addSubsetPhrase(subset, phraseName, value);
                String[] array = getValueArray(subset.getMetadata().getPhrases().getPhrase(phraseName), value);
                parseResultBuilder.addResult(idString, idString, array, lineNumber);
                return true;
            }
        }
    }

    private static String toPhraseName(String s) {
        if (s.startsWith("phrase_")) {
            return s.substring("phrase_".length());
        } else {
            return null;
        }
    }

    private String[] getValueArray(Labels oldLabels, CleanedString value) {
        String oldValue = "";
        if (oldLabels != null) {
            Label label = oldLabels.getLabel(lang);
            if (label != null) {
                oldValue = label.getLabelString();
            }
        }
        String newValue = "";
        if (value != null) {
            newValue = value.toString();
        }
        String[] array = {oldValue, newValue};
        return array;
    }

    private String[] getValueArray(CorpusField corpusField, CleanedString value) {
        String oldValue = "";
        Label label = corpusField.getLabels().getLabel(lang);
        if (label != null) {
            oldValue = label.getLabelString();
        }
        String newValue = "";
        if (value != null) {
            newValue = value.toString();
        }
        String[] array = {oldValue, newValue};
        return array;
    }

    private String[] getValueArray(Corpus corpus, IncludeKey includeKey, CleanedString value) {
        UiComponents uiComponents = bdfServer.getUiManager().getMainUiComponents(corpus);
        IncludeUi includeUi = (IncludeUi) uiComponents.getUiComponent(includeKey);
        String oldValue = "";
        if (includeUi != null) {
            Labels labels = includeUi.getCustomLabels();
            if (labels != null) {
                Label label = labels.getLabel(lang);
                if (label != null) {
                    oldValue = label.getLabelString();
                }
            }
        }
        String newValue = "";
        if (value != null) {
            newValue = value.toString();
        }
        String[] array = {oldValue, newValue};
        return array;
    }

}
