/* FichothequeLib_Tools - Copyright (c) 2010-2024 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.AbstractList;
import java.util.List;
import java.util.RandomAccess;
import net.fichotheque.Fichotheque;
import net.fichotheque.Subset;
import net.fichotheque.SubsetKey;
import net.fichotheque.extraction.def.AddendaExtractDef;
import net.fichotheque.extraction.def.AlbumExtractDef;
import net.fichotheque.extraction.def.CorpusExtractDef;
import net.fichotheque.extraction.def.DocumentFilter;
import net.fichotheque.extraction.def.FicheFilter;
import net.fichotheque.extraction.def.IllustrationFilter;
import net.fichotheque.extraction.def.MotcleFilter;
import net.fichotheque.extraction.def.SubsetExtractDef;
import net.fichotheque.extraction.def.ThesaurusExtractDef;
import net.fichotheque.extraction.filterunit.FilterUnit;
import net.fichotheque.include.ExtendedIncludeKey;
import net.fichotheque.selection.CroisementCondition;
import net.fichotheque.selection.DocumentQuery;
import net.fichotheque.selection.FicheQuery;
import net.fichotheque.selection.IllustrationQuery;
import net.fichotheque.selection.MotcleQuery;
import net.fichotheque.thesaurus.Thesaurus;
import net.fichotheque.tools.selection.DocumentQueryBuilder;
import net.fichotheque.tools.selection.FicheQueryBuilder;
import net.fichotheque.tools.selection.IllustrationQueryBuilder;
import net.fichotheque.tools.selection.MotcleQueryBuilder;
import net.fichotheque.utils.FilterUnits;
import net.fichotheque.utils.SelectionUtils;
import net.fichotheque.xml.extraction.ExtractionXMLUtils;
import net.mapeadores.util.exceptions.SwitchException;


/**
 *
 * @author Vincent Calame
 */
public final class ExtractionBuilderUtils {

    private ExtractionBuilderUtils() {
    }

    public static FilterUnit getDefaultFilterUnit(ExtendedIncludeKey includeKey, Fichotheque fichotheque) {
        SubsetExtractDef extractDef = getDefaultExtractDef(includeKey, fichotheque);
        switch (extractDef.getCategory()) {
            case SubsetKey.CATEGORY_CORPUS:
                return FilterUnits.defaultCorpusExtract((CorpusExtractDef) extractDef, includeKey);
            case SubsetKey.CATEGORY_THESAURUS:
                return FilterUnits.defaultThesaurusExtract((ThesaurusExtractDef) extractDef, includeKey);
            case SubsetKey.CATEGORY_ALBUM:
                return FilterUnits.defaultAlbumExtract((AlbumExtractDef) extractDef, includeKey);
            case SubsetKey.CATEGORY_ADDENDA:
                return FilterUnits.defaultAddendaExtract((AddendaExtractDef) extractDef, includeKey);
            default:
                throw new SwitchException("Unknown category: " + includeKey.getCategory());
        }
    }

    public static SubsetExtractDef getDefaultExtractDef(ExtendedIncludeKey includeKey, Fichotheque fichotheque) {
        switch (includeKey.getCategory()) {
            case SubsetKey.CATEGORY_CORPUS:
                return getCorpusExtractDef(includeKey, ExtractionXMLUtils.TITLE_FICHEFILTER);
            case SubsetKey.CATEGORY_THESAURUS:
                return getThesaurusExtractDef(includeKey, getDefaultMotcleFilter(includeKey, fichotheque));
            case SubsetKey.CATEGORY_ALBUM:
                return getAlbumExtractDef(includeKey, ExtractionXMLUtils.DEFAULT_ILLUSTRATIONFILTER);
            case SubsetKey.CATEGORY_ADDENDA:
                return getAddendaExtractDef(includeKey, ExtractionXMLUtils.DEFAULT_DOCUMENTFILTER);
            default:
                throw new SwitchException("Unknown category: " + includeKey.getCategory());
        }
    }

    private static MotcleFilter getDefaultMotcleFilter(ExtendedIncludeKey includeKey, Fichotheque fichotheque) {
        boolean withFicheStylePhrase = false;
        Subset subset = fichotheque.getSubset(includeKey.getSubsetKey());
        if (subset != null) {
            withFicheStylePhrase = ((Thesaurus) subset).getThesaurusMetadata().isWithFicheStyle();
        }
        return MotcleFilterBuilder.init(MotcleFilter.DEFAULT_TYPE)
                .setWithIcon(true)
                .setWithLabels(true)
                .setWithFicheStylePhrase(withFicheStylePhrase)
                .toMotcleFilter();
    }

    public static CorpusExtractDef getCorpusExtractDef(ExtendedIncludeKey includeKey, FicheFilter ficheFilter) {
        if (!includeKey.getSubsetKey().isCorpusSubset()) {
            throw new IllegalArgumentException("Not a corpus subsetkey");
        }
        FicheQuery ficheQuery = FicheQueryBuilder.init()
                .addCorpus(includeKey.getSubsetKey())
                .toFicheQuery();
        CroisementCondition croisementCondition = SelectionUtils.toCroisementCondition(includeKey);
        return CorpusExtractDefBuilder.init(ficheFilter)
                .setName(includeKey.getKeyString())
                .setBoolean(CorpusExtractDef.MASTER_BOOLEAN, includeKey.isMaster())
                .setEntryList(SelectionUtils.toFicheConditionEntry(ficheQuery, croisementCondition, false))
                .toCorpusExtractDef();
    }

    public static ThesaurusExtractDef getThesaurusExtractDef(ExtendedIncludeKey includeKey, MotcleFilter motcleFilter) {
        if (!includeKey.getSubsetKey().isThesaurusSubset()) {
            throw new IllegalArgumentException("Not a thesaurus subsetkey");
        }
        MotcleQuery motcleQuery = MotcleQueryBuilder.init()
                .addThesaurus(includeKey.getSubsetKey())
                .toMotcleQuery();
        CroisementCondition croisementCondition = SelectionUtils.toCroisementCondition(includeKey);
        return ThesaurusExtractDefBuilder.init(motcleFilter)
                .setName(includeKey.getKeyString())
                .setBoolean(ThesaurusExtractDef.MASTER_BOOLEAN, includeKey.isMaster())
                .setEntryList(SelectionUtils.toMotcleConditionEntry(motcleQuery, croisementCondition, false))
                .toThesaurusExtractDef();
    }

    public static AlbumExtractDef getAlbumExtractDef(ExtendedIncludeKey includeKey, IllustrationFilter illustrationFilter) {
        if (!includeKey.getSubsetKey().isAlbumSubset()) {
            throw new IllegalArgumentException("Not a album subsetkey");
        }
        IllustrationQuery illustrationQuery = IllustrationQueryBuilder.init()
                .addAlbum(includeKey.getSubsetKey())
                .toIllustrationQuery();
        CroisementCondition croisementCondition = SelectionUtils.toCroisementCondition(includeKey);
        return AlbumExtractDefBuilder.init(illustrationFilter)
                .setName(includeKey.getKeyString())
                .setEntryList(SelectionUtils.toIllustrationConditionEntry(illustrationQuery, croisementCondition))
                .toAlbumExtractDef();
    }

    public static AddendaExtractDef getAddendaExtractDef(ExtendedIncludeKey includeKey, DocumentFilter documentFilter) {
        if (!includeKey.getSubsetKey().isAddendaSubset()) {
            throw new IllegalArgumentException("Not a addenda subsetkey");
        }
        DocumentQuery documentQuery = DocumentQueryBuilder.init()
                .addAddenda(includeKey.getSubsetKey())
                .toDocumentQuery();
        CroisementCondition croisementCondition = SelectionUtils.toCroisementCondition(includeKey);
        return AddendaExtractDefBuilder.init(documentFilter)
                .setName(includeKey.getKeyString())
                .setEntryList(SelectionUtils.toDocumentConditionEntry(documentQuery, croisementCondition))
                .toAddendaExtractDef();
    }

    public static List<CorpusExtractDef> wrap(CorpusExtractDef[] array) {
        return new CorpusExtractDefList(array);
    }


    private static class CorpusExtractDefList extends AbstractList<CorpusExtractDef> implements RandomAccess {

        private final CorpusExtractDef[] array;

        private CorpusExtractDefList(CorpusExtractDef[] array) {
            this.array = array;
        }

        @Override
        public int size() {
            return array.length;
        }

        @Override
        public CorpusExtractDef get(int index) {
            return array[index];
        }

    }

}
