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

import java.util.ArrayList;
import java.util.List;
import net.fichotheque.extraction.def.CorpusExtractDef;
import net.fichotheque.extraction.def.MotcleFilter;
import net.fichotheque.extraction.def.TagNameInfo;
import net.fichotheque.extraction.filterunit.FilterUnit;
import net.fichotheque.utils.ExtractionUtils;
import net.fichotheque.utils.FilterUnits;
import net.fichotheque.xml.extraction.ExtractionXMLUtils;


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

    private final static CorpusExtractDef DEFAULT_INDEXATION_DEF = CorpusExtractDefBuilder
            .init(ExtractionXMLUtils.TITLE_FICHEFILTER)
            .setClause(CorpusExtractDef.TITLE_CLAUSE, TitleClauseBuilder.DEFAULT)
            .toCorpusExtractDef();
    private final short type;
    private final List<FilterUnit> filterUnitList = new ArrayList<FilterUnit>();
    private TagNameInfo tagNameInfo = TagNameInfo.DEFAULT;
    private boolean withIcon = false;
    private boolean withLevel = false;
    private boolean withLabels = false;
    private boolean withFicheStylePhrase = false;
    private MotcleFilter previousFilter = null;
    private MotcleFilter nextFilter = null;
    private boolean parentRecursive = false;
    private MotcleFilter parentFilter = null;
    private boolean childrenRecursive = false;
    private MotcleFilter childrenFilter = null;


    public MotcleFilterBuilder(short type) {
        this.type = type;
    }

    public short getType() {
        return type;
    }

    public MotcleFilterBuilder add(FilterUnit filterUnit) {
        if (filterUnit == null) {
            throw new NullPointerException("filterUnit is null");
        }
        filterUnitList.add(filterUnit);
        return this;
    }

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

    public MotcleFilterBuilder setWithIcon(boolean withIcon) {
        this.withIcon = withIcon;
        return this;
    }

    public MotcleFilterBuilder setWithLevel(boolean withLevel) {
        this.withLevel = withLevel;
        return this;
    }

    public MotcleFilterBuilder setWithFicheStylePhrase(boolean withFicheStylePhrase) {
        this.withFicheStylePhrase = withFicheStylePhrase;
        return this;
    }

    public MotcleFilterBuilder setChildrenFilter(MotcleFilter childrenFilter) {
        this.childrenRecursive = false;
        this.childrenFilter = childrenFilter;
        return this;
    }

    public MotcleFilterBuilder setParentFilter(MotcleFilter parentFilter) {
        this.parentRecursive = false;
        this.parentFilter = parentFilter;
        return this;
    }

    public MotcleFilterBuilder setNextFilter(MotcleFilter nextFilter) {
        this.nextFilter = nextFilter;
        return this;
    }

    public MotcleFilterBuilder setWithLabels(boolean withLabels) {
        this.withLabels = withLabels;
        return this;
    }

    public MotcleFilterBuilder setPreviousFilter(MotcleFilter previousFilter) {
        this.previousFilter = previousFilter;
        return this;
    }

    public MotcleFilterBuilder addDefaultCorpusExtractDef() {
        add(FilterUnits.corpusExtract(DEFAULT_INDEXATION_DEF, ExtractionUtils.EMPTY_FILTERPARAMETERS));
        return this;
    }

    public MotcleFilterBuilder setRecursive() {
        switch (type) {
            case MotcleFilter.DEFAULT_TYPE:
                setChildrenRecursive();
                break;
            case MotcleFilter.PARENT_TYPE:
                setParentRecursive();
                break;
        }
        return this;
    }

    public MotcleFilterBuilder setChildrenRecursive() {
        this.childrenRecursive = true;
        this.childrenFilter = null;
        return this;
    }

    public MotcleFilterBuilder setParentRecursive() {
        this.parentRecursive = true;
        this.parentFilter = null;
        return this;
    }

    public MotcleFilter toMotcleFilter() {
        List<FilterUnit> finalFilterUnitList = ExtractionUtils.toImmutableList(filterUnitList);
        return new InternalMotcleFilter(type, tagNameInfo, withIcon, withLevel, withLabels, withFicheStylePhrase,
                previousFilter, nextFilter, parentRecursive, parentFilter, childrenRecursive, childrenFilter, finalFilterUnitList);
    }

    public static MotcleFilterBuilder init(short type) {
        return new MotcleFilterBuilder(type);
    }


    private static class InternalMotcleFilter implements MotcleFilter {

        private final short type;
        private final TagNameInfo tagNameInfo;
        private final boolean withIcon;
        private final boolean withLevel;
        private final boolean withLabels;
        private final boolean withFicheStylePhrase;
        private final MotcleFilter previousFilter;
        private final MotcleFilter nextFilter;
        private final boolean parentRecursive;
        private final MotcleFilter parentFilter;
        private final boolean childrenRecursive;
        private final MotcleFilter childrenFilter;
        private final List<FilterUnit> filterUnitList;

        private InternalMotcleFilter(short type, TagNameInfo tagNameInfo, boolean withIcon, boolean withLevel, boolean withLabels, boolean withFicheStylePhrase,
                MotcleFilter previousFilter, MotcleFilter nextFilter, boolean parentRecursive, MotcleFilter parentFilter, boolean childrenRecursive, MotcleFilter childrenFilter,
                List<FilterUnit> filterUnitList) {
            this.type = type;
            this.tagNameInfo = tagNameInfo;
            this.withIcon = withIcon;
            this.withLevel = withLevel;
            this.withLabels = withLabels;
            this.withFicheStylePhrase = withFicheStylePhrase;
            this.previousFilter = previousFilter;
            this.nextFilter = nextFilter;
            this.parentRecursive = parentRecursive;
            this.parentFilter = parentFilter;
            this.childrenRecursive = childrenRecursive;
            this.childrenFilter = childrenFilter;
            this.filterUnitList = filterUnitList;
        }

        @Override
        public short getType() {
            return type;
        }

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

        @Override
        public boolean isNoneFiltering() {
            if (withLabels) {
                return false;
            }
            if (withLevel) {
                return false;
            }
            if (withFicheStylePhrase) {
                return false;
            }
            if (previousFilter != null) {
                return false;
            }
            if (nextFilter != null) {
                return false;
            }
            if ((parentRecursive) || (parentFilter != null)) {
                return false;
            }
            if ((childrenRecursive) || (childrenFilter != null)) {
                return false;
            }
            if (!filterUnitList.isEmpty()) {
                return false;
            }
            return true;
        }

        @Override
        public boolean withIcon() {
            return withIcon;
        }

        @Override
        public boolean withLevel() {
            return withLevel;
        }

        @Override
        public boolean withLabels() {
            return withLabels;
        }

        @Override
        public boolean withFicheStylePhrase() {
            return withFicheStylePhrase;
        }

        @Override
        public MotcleFilter getChildrenFilter() {
            if (childrenRecursive) {
                return this;
            } else {
                return childrenFilter;
            }
        }

        @Override
        public MotcleFilter getParentFilter() {
            if (parentRecursive) {
                return this;
            } else {
                return parentFilter;
            }
        }

        @Override
        public MotcleFilter getNextFilter() {
            return nextFilter;
        }

        @Override
        public MotcleFilter getPreviousFilter() {
            return previousFilter;
        }

        @Override
        public List<FilterUnit> getFilterUnitList() {
            return filterUnitList;
        }


    }

}
