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

import java.text.ParseException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import net.fichotheque.SubsetKey;
import net.fichotheque.exportation.scrutari.CorpusScrutariDef;
import net.fichotheque.exportation.scrutari.ScrutariExportDef;
import net.fichotheque.exportation.scrutari.ThesaurusScrutariDef;
import net.fichotheque.selection.SelectionOptions;
import net.fichotheque.tools.selection.FichothequeQueriesBuilder;
import net.fichotheque.tools.selection.SelectionOptionsBuilder;
import net.fichotheque.utils.FichothequeUtils;
import net.mapeadores.util.attr.Attributes;
import net.mapeadores.util.localisation.Lang;
import net.mapeadores.util.localisation.Langs;
import net.mapeadores.util.localisation.LangsUtils;
import net.mapeadores.util.misc.DefBuilder;
import net.mapeadores.util.text.AccoladePattern;
import net.mapeadores.util.text.Label;
import net.mapeadores.util.text.LabelChangeBuilder;
import net.mapeadores.util.text.Labels;
import net.mapeadores.util.text.RelativePath;
import net.mapeadores.util.text.StringUtils;
import net.scrutari.dataexport.api.BaseMetadataExport;


/**
 *
 * @author Vincent Calame
 */
public class ScrutariExportDefBuilder extends DefBuilder {

    private final Set<SubsetKey> subsetKeySet = new HashSet<SubsetKey>();
    private final LabelChangeBuilder shortLabelBuilder = new LabelChangeBuilder();
    private final LabelChangeBuilder longLabelBuilder = new LabelChangeBuilder();
    private final FichothequeQueriesBuilder customFichothequeQueriesBuilder = new FichothequeQueriesBuilder();
    private final SelectionOptionsBuilder selectionOptionsBuilder = new SelectionOptionsBuilder();
    private final String name;
    private final List<CorpusScrutariDef> corpusScrutariDefList = new ArrayList<CorpusScrutariDef>();
    private final List<ThesaurusScrutariDef> thesaurusScrutariDefList = new ArrayList<ThesaurusScrutariDef>();
    private final Set<Lang> uiLangSet = new LinkedHashSet<Lang>();
    private final Set<String> includeTokenSet = new LinkedHashSet<String>();
    private String authority;
    private String baseName;
    private String baseIcon = "";
    private AccoladePattern ficheHrefPattern;
    private AccoladePattern motcleHrefPattern;
    private String targetName = "";
    private RelativePath targetPath = RelativePath.EMPTY;
    private String selectionDefName = "";

    public ScrutariExportDefBuilder(String name, String authority, String baseName) {
        this(name, authority, baseName, null);
    }

    public ScrutariExportDefBuilder(String name, String authority, String baseName, Attributes initAttributes) {
        super(initAttributes);
        try {
            ScrutariExportDef.checkScrutariExportName(name);
        } catch (ParseException pe) {
            throw new IllegalArgumentException("Wrong name: " + name);
        }
        if (!StringUtils.isAuthority(authority)) {
            throw new IllegalArgumentException("wrong authority");
        }
        if (!StringUtils.isTechnicalName(baseName, true)) {
            throw new IllegalArgumentException("wrong baseName");
        }
        this.name = name;
        this.authority = authority;
        this.baseName = baseName;
    }

    public FichothequeQueriesBuilder getCustomFichothequeQueriesBuilder() {
        return customFichothequeQueriesBuilder;
    }

    public SelectionOptionsBuilder getSelectionOptionsBuilder() {
        return selectionOptionsBuilder;
    }

    public ScrutariExportDefBuilder setAuthority(String authority) throws ParseException {
        if (authority == null) {
            throw new IllegalArgumentException("authority is null");
        }
        StringUtils.checkAuthority(authority);
        this.authority = authority;
        return this;
    }

    public ScrutariExportDefBuilder setBaseName(String baseName) throws ParseException {
        if (baseName == null) {
            throw new IllegalArgumentException("baseName is null");
        }
        StringUtils.checkTechnicalName(baseName, true);
        this.baseName = baseName;
        return this;
    }

    public ScrutariExportDefBuilder setBaseIcon(String baseIcon) {
        this.baseIcon = StringUtils.nullTrim(baseIcon);
        return this;
    }

    public ScrutariExportDefBuilder setFicheHrefPattern(AccoladePattern ficheHrefPattern) {
        this.ficheHrefPattern = ficheHrefPattern;
        return this;
    }

    public ScrutariExportDefBuilder setMotcleHrefPattern(AccoladePattern motcleHrefPattern) {
        this.motcleHrefPattern = motcleHrefPattern;
        return this;
    }

    public ScrutariExportDefBuilder addCorpusScrutariDef(CorpusScrutariDef corpusScrutariDef) {
        if (!subsetKeySet.contains(corpusScrutariDef.getCorpusKey())) {
            subsetKeySet.add(corpusScrutariDef.getCorpusKey());
            corpusScrutariDefList.add(corpusScrutariDef);
        }
        return this;
    }

    public ScrutariExportDefBuilder addThesaurusScrutariDef(ThesaurusScrutariDef thesaurusScrutariDef) {
        if (!subsetKeySet.contains(thesaurusScrutariDef.getThesaurusKey())) {
            subsetKeySet.add(thesaurusScrutariDef.getThesaurusKey());
            thesaurusScrutariDefList.add(thesaurusScrutariDef);
        }
        return this;
    }

    public ScrutariExportDefBuilder addLang(Lang lang) {
        uiLangSet.add(lang);
        return this;
    }

    public ScrutariExportDefBuilder putBaseLabel(int baseIntituleType, Label label) {
        switch (baseIntituleType) {
            case BaseMetadataExport.INTITULE_LONG:
                longLabelBuilder.putLabel(label);
                break;
            case BaseMetadataExport.INTITULE_SHORT:
                shortLabelBuilder.putLabel(label);
                break;
            default:
                throw new IllegalArgumentException("Unknown baseIntituleType: " + baseIntituleType);
        }
        return this;
    }

    public ScrutariExportDefBuilder setTargetName(String targetName) {
        this.targetName = StringUtils.nullTrim(targetName);
        return this;
    }

    public ScrutariExportDefBuilder setTargetPath(RelativePath targetPath) {
        if (targetPath == null) {
            targetPath = RelativePath.EMPTY;
        }
        this.targetPath = targetPath;
        return this;
    }

    public ScrutariExportDefBuilder addIncludeToken(String includeToken) {
        if ((includeToken != null) && (includeToken.length() > 0)) {
            includeTokenSet.add(includeToken);
        }
        return this;
    }

    public ScrutariExportDefBuilder parseIncludeTokens(String includeTokens) {
        if (includeTokens != null) {
            String[] tokens = StringUtils.getTechnicalTokens(includeTokens, true);
            for (String token : tokens) {
                includeTokenSet.add(token);
            }
        }
        return this;
    }

    public ScrutariExportDef toScrutariExportDef() {
        Labels shortLabels = shortLabelBuilder.toLabels();
        if (shortLabels.isEmpty()) {
            shortLabels = null;
        }
        Labels longLabels = longLabelBuilder.toLabels();
        if (longLabels.isEmpty()) {
            longLabels = null;
        }
        List<CorpusScrutariDef> finalCorpusScrutariDefList = FichothequeUtils.wrap(corpusScrutariDefList.toArray(new CorpusScrutariDef[corpusScrutariDefList.size()]));
        List<ThesaurusScrutariDef> finalThesaurusScrutariDefList = FichothequeUtils.wrap(thesaurusScrutariDefList.toArray(new ThesaurusScrutariDef[thesaurusScrutariDefList.size()]));
        Labels titleLabels = toLabels();
        Attributes attributes = toAttributes();
        Langs finalUiLangs = LangsUtils.wrap(uiLangSet);
        List<String> includeTokenList = StringUtils.toList(includeTokenSet);
        return new InternalScrutariExportDef(name, authority, baseName, baseIcon, finalUiLangs, shortLabels, longLabels, selectionOptionsBuilder.toSelectionOptions(), ficheHrefPattern, motcleHrefPattern, finalCorpusScrutariDefList, finalThesaurusScrutariDefList, targetName, targetPath, titleLabels, attributes, includeTokenList);
    }

    public static ScrutariExportDefBuilder init(String name, String authority, String baseName) {
        return new ScrutariExportDefBuilder(name, authority, baseName, null);
    }

    public static ScrutariExportDefBuilder init(String name, String authority, String baseName, Attributes initAttributes) {
        return new ScrutariExportDefBuilder(name, authority, baseName, initAttributes);
    }


    private static class InternalScrutariExportDef implements ScrutariExportDef {

        private final String name;
        private final String authority;
        private final String baseName;
        private final String baseIcon;
        private final Langs uiLangs;
        private final Labels shortIntitule;
        private final Labels longIntitule;
        private final SelectionOptions selectionOptions;
        private final AccoladePattern ficheHrefPattern;
        private final AccoladePattern motcleHrefPattern;
        private final List<CorpusScrutariDef> corpusScrutariDefList;
        private final List<ThesaurusScrutariDef> thesaurusScrutariDefList;
        private final String targetName;
        private final RelativePath targetPath;
        private final Labels titleLabels;
        private final Attributes attributes;
        private final List<String> includeTokenList;


        private InternalScrutariExportDef(String name, String authority, String baseName, String baseIcon, Langs uiLangs, Labels shortIntitule, Labels longIntitule, SelectionOptions selectionOptions, AccoladePattern ficheHrefPattern, AccoladePattern motcleHrefPattern, List<CorpusScrutariDef> corpusScrutariDefList, List<ThesaurusScrutariDef> thesaurusScrutariDefList, String targetName, RelativePath targetPath,
                Labels titleLabels, Attributes attributes, List<String> includeTokenList) {
            this.name = name;
            this.authority = authority;
            this.baseName = baseName;
            this.baseIcon = baseIcon;
            this.uiLangs = uiLangs;
            this.shortIntitule = shortIntitule;
            this.longIntitule = longIntitule;
            this.selectionOptions = selectionOptions;
            this.ficheHrefPattern = ficheHrefPattern;
            this.motcleHrefPattern = motcleHrefPattern;
            this.corpusScrutariDefList = corpusScrutariDefList;
            this.thesaurusScrutariDefList = thesaurusScrutariDefList;
            this.targetName = targetName;
            this.targetPath = targetPath;
            this.titleLabels = titleLabels;
            this.attributes = attributes;
            this.includeTokenList = includeTokenList;
        }

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

        @Override
        public String getAuthority() {
            return authority;
        }

        @Override
        public String getBaseName() {
            return baseName;
        }

        @Override
        public String getBaseIcon() {
            return baseIcon;
        }

        @Override
        public Labels getTitleLabels() {
            return titleLabels;
        }

        @Override
        public Attributes getAttributes() {
            return attributes;
        }

        @Override
        public AccoladePattern getFicheHrefPattern() {
            return ficheHrefPattern;
        }

        @Override
        public AccoladePattern getMotcleHrefPattern() {
            return motcleHrefPattern;
        }

        @Override
        public List<CorpusScrutariDef> getCorpusScrutariDefList() {
            return corpusScrutariDefList;
        }

        @Override
        public List<ThesaurusScrutariDef> getThesaurusScrutariDefList() {
            return thesaurusScrutariDefList;
        }

        @Override
        public SelectionOptions getSelectionOptions() {
            return selectionOptions;
        }

        @Override
        public Langs getUiLangs() {
            return uiLangs;
        }

        @Override
        public Labels getCustomBaseIntitule(int baseIntituleType) {
            switch (baseIntituleType) {
                case BaseMetadataExport.INTITULE_LONG:
                    return longIntitule;
                case BaseMetadataExport.INTITULE_SHORT:
                    return shortIntitule;
                default:
                    return null;
            }
        }

        @Override
        public String getTargetName() {
            return targetName;
        }

        @Override
        public RelativePath getTargetPath() {
            return targetPath;
        }

        @Override
        public List<String> getIncludeTokenList() {
            return includeTokenList;
        }

    }

}
