/* FichothequeLib_Tools - Copyright (c) 2011-2022 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.extraction.builders;

import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import net.fichotheque.extraction.def.CorpusExtractDef;
import net.fichotheque.extraction.def.FicheFilter;
import net.fichotheque.extraction.def.GroupClause;
import net.fichotheque.extraction.def.PackClause;
import net.fichotheque.extraction.def.TagNameInfo;
import net.fichotheque.extraction.def.TitleClause;
import net.fichotheque.selection.FicheCondition;
import net.fichotheque.utils.SelectionUtils;


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

    private final Map<String, Boolean> booleanMap = new HashMap<String, Boolean>();
    private final Map<String, Object> clauseMap = new HashMap<String, Object>();
    private FicheFilter ficheFilter;
    private String name = null;
    private TagNameInfo tagNameInfo = TagNameInfo.DEFAULT;
    private List<FicheCondition.Entry> ficheQueryList = SelectionUtils.EMPTY_FICHECONDITIONENTRYLIST;

    public CorpusExtractDefBuilder() {

    }

    public CorpusExtractDefBuilder(FicheFilter ficheFilter) {
        if (ficheFilter == null) {
            throw new IllegalArgumentException("ficheFilter is null");
        }
        this.ficheFilter = ficheFilter;
    }

    public CorpusExtractDefBuilder setFicheFilter(FicheFilter ficheFilter) {
        if (ficheFilter == null) {
            throw new IllegalArgumentException("ficheFilter is null");
        }
        this.ficheFilter = ficheFilter;
        return this;
    }

    public CorpusExtractDefBuilder setName(String name) {
        if ((name != null) && (name.length() == 0)) {
            name = null;
        }
        this.name = name;
        return this;
    }

    public CorpusExtractDefBuilder setTagNameInfo(TagNameInfo tagNameInfo) {
        this.tagNameInfo = tagNameInfo;
        return this;
    }

    public CorpusExtractDefBuilder setEntryList(List<FicheCondition.Entry> list) {
        this.ficheQueryList = list;
        return this;
    }

    public CorpusExtractDefBuilder setEntryList(FicheCondition.Entry ficheQuery) {
        this.ficheQueryList = Collections.singletonList(ficheQuery);
        return this;
    }

    public CorpusExtractDefBuilder setBoolean(String name, boolean value) {
        if (value) {
            booleanMap.put(name, Boolean.TRUE);
        } else {
            booleanMap.remove(name);
        }
        return this;
    }

    public CorpusExtractDefBuilder setClause(String name, Object clauseObject) {
        if (clauseObject != null) {
            switch (name) {
                case CorpusExtractDef.GROUP_CLAUSE:
                    clauseObject = (GroupClause) clauseObject;
                    break;
                case CorpusExtractDef.PACK_CLAUSE:
                    clauseObject = (PackClause) clauseObject;
                    break;
                case CorpusExtractDef.TITLE_CLAUSE:
                    clauseObject = (TitleClause) clauseObject;
                    break;
            }
            clauseMap.put(name, clauseObject);
        } else {
            clauseMap.remove(name);
        }
        return this;
    }

    public CorpusExtractDef toCorpusExtractDef() {
        if (ficheFilter == null) {
            throw new IllegalStateException("ficheFilter is null");
        }
        Map<String, Boolean> finalBooleanMap = new HashMap<String, Boolean>(booleanMap);
        Map<String, Object> finalClauseMap = new HashMap<String, Object>(clauseMap);
        return new InternalCorpusExtractDef(ficheFilter, name, tagNameInfo, ficheQueryList, finalBooleanMap, finalClauseMap);
    }

    public static CorpusExtractDefBuilder init() {
        return new CorpusExtractDefBuilder();
    }

    public static CorpusExtractDefBuilder init(FicheFilter ficheFilter) {
        return new CorpusExtractDefBuilder(ficheFilter);
    }


    private static class InternalCorpusExtractDef implements CorpusExtractDef {

        private final FicheFilter ficheFilter;
        private final String name;
        private final TagNameInfo tagNameInfo;
        private final List<FicheCondition.Entry> entryList;
        private final Map<String, Boolean> booleanMap;
        private final Map<String, Object> clauseMap;


        private InternalCorpusExtractDef(FicheFilter ficheFilter, String name, TagNameInfo tagNameInfo, List<FicheCondition.Entry> entryList, Map<String, Boolean> booleanMap, Map<String, Object> clauseMap) {
            this.ficheFilter = ficheFilter;
            this.name = name;
            this.tagNameInfo = tagNameInfo;
            this.entryList = entryList;
            this.booleanMap = booleanMap;
            this.clauseMap = clauseMap;
        }

        @Override
        public TagNameInfo getTagNameInfo() {
            return tagNameInfo;
        }

        @Override
        public String getName() {
            return name;
        }

        @Override
        public FicheFilter getFicheFilter() {
            return ficheFilter;
        }

        @Override
        public List<FicheCondition.Entry> getConditionEntryList() {
            return entryList;
        }

        @Override
        public boolean hasClauseObjects() {
            return !clauseMap.isEmpty();
        }

        @Override
        public Object getClauseObject(String name) {
            return clauseMap.get(name);
        }

        @Override
        public boolean hasBooleanParameters() {
            return !booleanMap.isEmpty();
        }

        @Override
        public boolean getBooleanParameter(String name) {
            return booleanMap.containsKey(name);
        }


    }

}
