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

import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import net.fichotheque.exportation.balayage.BalayageConstants;
import net.fichotheque.exportation.balayage.BalayageDef;
import net.fichotheque.exportation.balayage.BalayagePostscriptum;
import net.fichotheque.exportation.balayage.BalayageUnit;
import net.fichotheque.selection.SelectionOptions;
import net.fichotheque.tools.selection.SelectionOptionsBuilder;
import net.fichotheque.utils.BalayageUtils;
import net.mapeadores.util.annotation.Nullable;
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.Labels;
import net.mapeadores.util.text.RelativePath;
import net.mapeadores.util.text.StringUtils;


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

    private final String name;
    private final SelectionOptionsBuilder selectionOptionsBuilder = new SelectionOptionsBuilder();
    private final BalayagePostscriptumBuilder balayagePostscriptumBuilder = new BalayagePostscriptumBuilder();
    private final Set<Lang> langSet = new LinkedHashSet<Lang>();
    private final List<BalayageUnitBuilder> unitList = new ArrayList<BalayageUnitBuilder>();
    private String targetName = "";
    private RelativePath targetPath = RelativePath.EMPTY;
    private String defaultLangOption = BalayageConstants.LANGOPTION_NONE;
    private boolean ignoreTransformation = false;

    public BalayageDefBuilder(String name) {
        this(name, null);
    }

    public BalayageDefBuilder(String name, @Nullable Attributes initAttributes) {
        super(initAttributes);
        if (!StringUtils.isTechnicalName(name, true)) {
            throw new IllegalArgumentException("Wrong syntax");
        }
        this.name = name;
    }

    public SelectionOptionsBuilder getSelectionOptionsBuilder() {
        return selectionOptionsBuilder;
    }

    public BalayagePostscriptumBuilder getBalayagePostscriptumBuilder() {
        return balayagePostscriptumBuilder;
    }

    public BalayageDefBuilder addLang(Lang lang) {
        langSet.add(lang);
        return this;
    }

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

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

    public BalayageDefBuilder setDefaultLangOption(String defaultLangOption) {
        defaultLangOption = BalayageConstants.checkLangOption(defaultLangOption);
        if (defaultLangOption.equals(BalayageConstants.LANGOPTION_UNKNOWN)) {
            defaultLangOption = BalayageConstants.LANGOPTION_NONE;
        }
        this.defaultLangOption = defaultLangOption;
        return this;
    }

    public BalayageDefBuilder setIgnoreTransformation(boolean ignoreTransformation) {
        this.ignoreTransformation = ignoreTransformation;
        return this;
    }

    public BalayageUnitBuilder addBalayageUnitBuilder(String type) {
        BalayageUnitBuilder unitBuilder = new BalayageUnitBuilder(type);
        unitList.add(unitBuilder);
        return unitBuilder;
    }

    public BalayageDef toBalayageDef() {
        List<BalayageUnit> balayageUnitList = BalayageUtils.EMPTY_UNITLIST;
        int unitLength = unitList.size();
        if (unitLength > 0) {
            BalayageUnit[] balayageUnitArray = new BalayageUnit[unitLength];
            for (int i = 0; i < unitLength; i++) {
                balayageUnitArray[i] = unitList.get(i).toBalayageUnit();
            }
            balayageUnitList = BalayageUtils.wrap(balayageUnitArray);
        }
        Labels titleLabels = toLabels();
        Attributes attributes = toAttributes();
        Langs langs = LangsUtils.fromCollection(langSet);
        return new InternalBalayageDef(name, langs, targetName, targetPath, defaultLangOption, ignoreTransformation, selectionOptionsBuilder.toSelectionOptions(), balayagePostscriptumBuilder.toBalayagePostscriptum(), balayageUnitList, titleLabels, attributes);
    }

    public static BalayageDefBuilder init(String name, @Nullable Attributes initAttributes) {
        return new BalayageDefBuilder(name, initAttributes);
    }


    private static class InternalBalayageDef implements BalayageDef {

        private final String name;
        private final Langs langs;
        private final String targetName;
        private final RelativePath targetPath;
        private final String defaultLangOption;
        private final boolean ignoreTransformation;
        private final SelectionOptions selectionOptions;
        private final BalayagePostscriptum balayagePostscriptum;
        private final List<BalayageUnit> balayageUnitList;
        private final Labels titleLabels;
        private final Attributes attributes;

        private InternalBalayageDef(String name, Langs langs, String targetName, RelativePath targetPath,
                String defaultLangOption, boolean ignoreTransformation, SelectionOptions selectionOptions, BalayagePostscriptum balayagePostscriptum, List<BalayageUnit> balayageUnitList,
                Labels titleLabels, Attributes attributes) {
            this.name = name;
            this.langs = langs;
            this.targetName = targetName;
            this.targetPath = targetPath;
            this.defaultLangOption = defaultLangOption;
            this.ignoreTransformation = ignoreTransformation;
            this.selectionOptions = selectionOptions;
            this.balayagePostscriptum = balayagePostscriptum;
            this.balayageUnitList = balayageUnitList;
            this.titleLabels = titleLabels;
            this.attributes = attributes;
        }

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

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

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

        @Override
        public Langs getLangs() {
            return langs;
        }

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

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

        @Override
        public String getDefaultLangOption() {
            return defaultLangOption;
        }

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

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

        @Override
        public BalayagePostscriptum getPostscriptum() {
            return balayagePostscriptum;
        }

        @Override
        public List<BalayageUnit> getBalayageUnitList() {
            return balayageUnitList;
        }

    }

}
