/* FichothequeLib_Tools  - Copyright (c) 2013-2021 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.alias;

import java.util.HashMap;
import java.util.Map;
import net.fichotheque.Fichotheque;
import net.fichotheque.SubsetKey;
import net.fichotheque.alias.AliasChecker;
import net.fichotheque.alias.AliasHolder;
import net.fichotheque.corpus.Corpus;
import net.fichotheque.corpus.metadata.CorpusField;
import net.fichotheque.corpus.metadata.FieldKey;
import net.fichotheque.thesaurus.Thesaurus;
import net.mapeadores.util.logging.MessageHandler;


/**
 *
 * @author Vincent Calame
 */
public class AliasHolderBuilder {

    private final Fichotheque fichotheque;
    private final MessageHandler messageHandler;
    private final AliasChecker aliasChecker;
    private final AliasHolder coreAliasHolder;
    private final Map<String, Corpus> corpusMap = new HashMap<String, Corpus>();
    private final Map<String, Thesaurus> thesaurusMap = new HashMap<String, Thesaurus>();
    private final Map<String, CorpusField> corpusFieldMap = new HashMap<String, CorpusField>();

    public AliasHolderBuilder(Fichotheque fichotheque, MessageHandler messageHandler, AliasChecker aliasChecker, AliasHolder coreAliasHolder) {
        this.fichotheque = fichotheque;
        this.messageHandler = messageHandler;
        this.aliasChecker = aliasChecker;
        this.coreAliasHolder = coreAliasHolder;
    }

    public AliasHolder toAliasHolder() {
        return new InternalAliasHolder(new HashMap<String, Corpus>(corpusMap), new HashMap<String, Thesaurus>(thesaurusMap), new HashMap<String, CorpusField>(corpusFieldMap));
    }

    public Corpus getCoreCorpus(String alias) {
        if (coreAliasHolder == null) {
            return null;
        }
        return coreAliasHolder.getCorpus(alias);
    }

    public Corpus initCorpus(String alias, SubsetKey corpusKey) {
        if (alias == null) {
            throw new IllegalArgumentException("alias is null");
        }
        if (corpusKey == null) {
            throw new IllegalArgumentException("corupsSubsetKey is null");
        }
        if (!corpusKey.isCorpusSubset()) {
            throw new IllegalArgumentException("!corpusKey.isCorpusSubset()");
        }
        short check = aliasChecker.checkCorpusAlias(alias);
        if (check == AliasChecker.UNKNOWN) {
            AliasUtils.unknownAlias(messageHandler, "corpus", alias);
            return null;
        }
        Corpus corpus = (Corpus) fichotheque.getSubset(corpusKey);
        if ((check == AliasChecker.MANDATORY) && (corpus == null)) {
            AliasUtils.missingSubset(messageHandler, alias, corpusKey);
            return null;
        }
        corpusMap.put(alias, corpus);
        return corpus;
    }

    public Thesaurus initThesaurus(String alias, SubsetKey thesaurusKey) {
        if (alias == null) {
            throw new IllegalArgumentException("alias is null");
        }
        if (thesaurusKey == null) {
            throw new IllegalArgumentException("thesaurusKey is null");
        }
        if (!thesaurusKey.isThesaurusSubset()) {
            throw new IllegalArgumentException("!thesaurusKey.isThesaurusSubset()");
        }
        short check = aliasChecker.checkThesaurusAlias(alias);
        if (check == AliasChecker.UNKNOWN) {
            AliasUtils.unknownAlias(messageHandler, "thesaurus", alias);
            return null;
        }
        Thesaurus thesaurus = (Thesaurus) fichotheque.getSubset(thesaurusKey);
        if ((check == AliasChecker.MANDATORY) && (thesaurus == null)) {
            AliasUtils.missingSubset(messageHandler, alias, thesaurusKey);
            return null;
        }
        thesaurusMap.put(alias, thesaurus);
        return thesaurus;
    }

    public void initField(Corpus corpus, String corpusAlias, String alias, FieldKey fieldKey) {
        if (alias == null) {
            throw new IllegalArgumentException("alias is null");
        }
        short check = aliasChecker.checkFieldAlias(corpusAlias, alias);
        if (check == AliasChecker.UNKNOWN) {
            AliasUtils.unknownAlias(messageHandler, "field", alias);
            return;
        }
        CorpusField corpusField = corpus.getCorpusMetadata().getCorpusField(fieldKey);
        if ((check == AliasChecker.MANDATORY) && (corpusField == null)) {
            AliasUtils.missingField(messageHandler, alias, fieldKey);
            return;
        }
        corpusFieldMap.put(alias, corpusField);
    }


    private class InternalAliasHolder implements AliasHolder {

        private final Map<String, Corpus> corpusMap;
        private final Map<String, Thesaurus> thesaurusMap;
        private final Map<String, CorpusField> corpusFieldMap;

        private InternalAliasHolder(Map<String, Corpus> corpusMap, Map<String, Thesaurus> thesaurusMap, Map<String, CorpusField> corpusFieldMap) {
            this.corpusMap = corpusMap;
            this.thesaurusMap = thesaurusMap;
            this.corpusFieldMap = corpusFieldMap;
        }

        @Override
        public Corpus getCorpus(String alias) {
            return corpusMap.get(alias);
        }

        @Override
        public Thesaurus getThesaurus(String alias) {
            return thesaurusMap.get(alias);
        }

        @Override
        public CorpusField getCorpusField(String alias) {
            return corpusFieldMap.get(alias);
        }

    }

}
