/* FichothequeLib_Tools - Copyright (c) 2015-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 net.fichotheque.tools.importation.parsers;

import java.text.ParseException;
import java.util.LinkedHashMap;
import java.util.Map;
import net.fichotheque.Fichotheque;
import net.fichotheque.thesaurus.metadata.ThesaurusFieldKey;
import net.fichotheque.thesaurus.metadata.ThesaurusMetadata;
import net.fichotheque.tools.importation.ParseResultBuilder;
import net.fichotheque.tools.importation.parsers.handlers.AttributeHandler;
import net.fichotheque.tools.importation.parsers.handlers.CroisementHandlers;
import net.fichotheque.tools.importation.parsers.handlers.IdalphaHandler;
import net.fichotheque.tools.importation.parsers.handlers.LabelHandler;
import net.fichotheque.tools.importation.thesaurus.ThesaurusImportBuilder;
import net.mapeadores.util.attr.AttributeKey;


/**
 *
 * @author Vincent Calame
 */
class ThesaurusColumns {

    private final static String BABELIEN_KEY = "babelien";
    private final int idIndex;
    private final int parentIdIndex;
    private final int statusIndex;
    private final IdalphaHandler idalphaHandler;
    private final IdalphaHandler parentIdalphaHandler;
    private final LabelHandler[] labelHandlerArray;
    private final AttributeHandler[] attributeHandlerArray;
    private final CroisementHandlers croisementHandlers;

    private ThesaurusColumns(int idIndex, int parentIdIndex, int statusIndex, IdalphaHandler idalphaHandler, IdalphaHandler parentIdalphaHandler, LabelHandler[] labelHandlerArray, AttributeHandler[] attributeHandlerArray, CroisementHandlers croisementHandlers) {
        this.idIndex = idIndex;
        this.parentIdIndex = parentIdIndex;
        this.statusIndex = statusIndex;
        this.labelHandlerArray = labelHandlerArray;
        this.idalphaHandler = idalphaHandler;
        this.parentIdalphaHandler = parentIdalphaHandler;
        this.attributeHandlerArray = attributeHandlerArray;
        this.croisementHandlers = croisementHandlers;
    }

    public int getIdIndex() {
        return idIndex;
    }

    public int getParentIdIndex() {
        return parentIdIndex;
    }

    public int getStatusIndex() {
        return statusIndex;
    }

    public IdalphaHandler getIdalphaHandler() {
        return idalphaHandler;
    }

    public IdalphaHandler getParentIdalphaHandler() {
        return parentIdalphaHandler;
    }

    public boolean hasLabelHandler() {
        return (labelHandlerArray != null);
    }

    public LabelHandler[] getLabelHandlerArray() {
        return labelHandlerArray;
    }

    public boolean hasAttributeHandler() {
        return (attributeHandlerArray != null);
    }

    public AttributeHandler[] getAttributeHandlerArray() {
        return attributeHandlerArray;
    }

    public boolean hasCroisementHandler() {
        return !croisementHandlers.isEmpty();
    }

    public CroisementHandlers getCroisementHandlers() {
        return croisementHandlers;
    }

    static ThesaurusColumns parse(String[] fieldArray, ThesaurusImportBuilder thesaurusImportBuilder, ParseResultBuilder parseResultBuilder) {
        short thesaurusType = thesaurusImportBuilder.getThesaurus().getThesaurusMetadata().getThesaurusType();
        Fichotheque fichotheque = thesaurusImportBuilder.getThesaurus().getFichotheque();
        boolean isBabelien = (thesaurusType == ThesaurusMetadata.BABELIEN_TYPE);
        boolean isIdalpha = (thesaurusType == ThesaurusMetadata.IDALPHA_TYPE);
        int idIndex = -1;
        int parentIdIndex = -1;
        int statusIndex = -1;
        IdalphaHandler idalphaHandler = null;
        IdalphaHandler parentIdalphaHandler = null;
        Map<Object, LabelHandler> labelHandlerMap = new LinkedHashMap<Object, LabelHandler>();
        Map<AttributeKey, AttributeHandler> attributeHandlerMap = new LinkedHashMap<AttributeKey, AttributeHandler>();
        CroisementHandlers croisementHandlers = new CroisementHandlers(false, false);
        int length = fieldArray.length;
        for (int i = 0; i < length; i++) {
            String field = fieldArray[i].trim();
            try {
                ThesaurusFieldKey thesaurusFieldKey = ThesaurusFieldKey.parse(field);
                if (thesaurusFieldKey.equals(ThesaurusFieldKey.ID)) {
                    if (idIndex == -1) {
                        idIndex = i;
                    } else {
                        parseResultBuilder.duplicateColumn(field);
                    }
                } else if (thesaurusFieldKey.equals(ThesaurusFieldKey.PARENT_ID)) {
                    if (parentIdIndex == -1) {
                        parentIdIndex = i;
                    } else {
                        parseResultBuilder.duplicateColumn(field);
                    }
                } else if (thesaurusFieldKey.equals(ThesaurusFieldKey.BABELIENLANG)) {
                    if (!isBabelien) {
                        parseResultBuilder.notAvailableColumn(field);
                    } else {
                        LabelHandler.Babelien babelienHandler = (LabelHandler.Babelien) labelHandlerMap.get(BABELIEN_KEY);
                        if (babelienHandler != null) {
                            babelienHandler = new LabelHandler.Babelien();
                            labelHandlerMap.put(BABELIEN_KEY, babelienHandler);
                        }
                        if (babelienHandler.hasLangIndex()) {
                            parseResultBuilder.duplicateColumn(field);
                        } else {
                            babelienHandler.setLangIndex(i);
                        }
                    }
                } else if (thesaurusFieldKey.equals(ThesaurusFieldKey.BABELIENLABEL)) {
                    if (!isBabelien) {
                        parseResultBuilder.notAvailableColumn(field);
                    } else {
                        LabelHandler.Babelien babelienHandler = (LabelHandler.Babelien) labelHandlerMap.get(BABELIEN_KEY);
                        if (babelienHandler != null) {
                            babelienHandler = new LabelHandler.Babelien();
                            labelHandlerMap.put(BABELIEN_KEY, babelienHandler);
                        }
                        babelienHandler.addIndex(i);
                    }
                } else if (thesaurusFieldKey.equals(ThesaurusFieldKey.IDALPHA)) {
                    if (!isIdalpha) {
                        parseResultBuilder.notUsableIdalpha(field);
                    } else {
                        if (idalphaHandler == null) {
                            idalphaHandler = new IdalphaHandler();
                        }
                        idalphaHandler.addIndex(i);
                    }
                } else if (thesaurusFieldKey.equals(ThesaurusFieldKey.PARENT_IDALPHA)) {
                    if (!isIdalpha) {
                        parseResultBuilder.notUsableIdalpha(field);
                    } else {
                        if (parentIdalphaHandler == null) {
                            parentIdalphaHandler = new IdalphaHandler();
                        }
                        parentIdalphaHandler.addIndex(i);
                    }
                } else if (thesaurusFieldKey.equals(ThesaurusFieldKey.STATUS)) {
                    if (statusIndex == -1) {
                        statusIndex = i;
                    } else {
                        parseResultBuilder.duplicateColumn(field);
                    }
                } else if (thesaurusFieldKey.isLabelThesaurusFieldKey()) {
                    if (isBabelien) {
                        parseResultBuilder.notAvailableColumn(field);
                    } else {
                        LabelHandler handler = labelHandlerMap.get(thesaurusFieldKey);
                        if (handler == null) {
                            handler = new LabelHandler.ByLang(thesaurusFieldKey.getLang());
                            labelHandlerMap.put(thesaurusFieldKey, handler);
                        }
                        handler.addIndex(i);
                    }
                } else {
                    parseResultBuilder.notAvailableColumn(field);
                }
            } catch (ParseException pe) {
                try {
                    AttributeKey attributeKey = AttributeKey.parse(field);
                    AttributeHandler attributeHandler = attributeHandlerMap.get(attributeKey);
                    if (attributeHandler == null) {
                        attributeHandler = new AttributeHandler(attributeKey);
                        attributeHandlerMap.put(attributeKey, attributeHandler);
                    }
                    attributeHandler.addIndex(i);
                } catch (ParseException pe2) {
                    if (!croisementHandlers.testCroisementHandlerCandidate(fichotheque, field, i, parseResultBuilder)) {
                        parseResultBuilder.wrongColumn(field);
                    }
                }
            }
        }
        LabelHandler.Babelien babelienHandler = (LabelHandler.Babelien) labelHandlerMap.get(BABELIEN_KEY);
        if (babelienHandler != null) {
            if (!babelienHandler.hasLangIndex()) {
                labelHandlerMap.remove(BABELIEN_KEY);
                parseResultBuilder.missingColumn(ThesaurusFieldKey.BABELIENLANG.toString());
            } else if (!babelienHandler.hasLibIndices()) {
                labelHandlerMap.remove(BABELIEN_KEY);
                parseResultBuilder.missingColumn(ThesaurusFieldKey.BABELIENLABEL.toString());
            }
        }
        LabelHandler[] labelHandlerArray = null;
        int labelHandlerSize = labelHandlerMap.size();
        if (labelHandlerSize > 0) {
            labelHandlerArray = labelHandlerMap.values().toArray(new LabelHandler[labelHandlerSize]);
        }
        AttributeHandler[] attributeHandlerArray = null;
        int attributeHandlerSize = attributeHandlerMap.size();
        if (attributeHandlerSize > 0) {
            attributeHandlerArray = attributeHandlerMap.values().toArray(new AttributeHandler[attributeHandlerSize]);
        }
        return new ThesaurusColumns(idIndex, parentIdIndex, statusIndex, idalphaHandler, parentIdalphaHandler, labelHandlerArray, attributeHandlerArray, croisementHandlers);
    }

}
