/* BdfServer - Copyright (c) 2015-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 fr.exemole.bdfserver.tools.ficheform;

import fr.exemole.bdfserver.api.BdfServer;
import fr.exemole.bdfserver.api.ficheform.FicheFormParameters;
import fr.exemole.bdfserver.api.instruction.BdfParameters;
import fr.exemole.bdfserver.api.users.BdfUser;
import fr.exemole.bdfserver.tools.roles.PermissionSummaryBuilder;
import java.text.DecimalFormatSymbols;
import java.util.HashMap;
import java.util.Map;
import net.fichotheque.SubsetItem;
import net.fichotheque.permission.PermissionSummary;
import net.fichotheque.sphere.Redacteur;
import net.fichotheque.syntax.FicheblockSyntax;
import net.fichotheque.syntax.FormSyntax;
import net.mapeadores.util.localisation.UserLangContext;
import net.mapeadores.util.request.RequestMap;
import net.mapeadores.util.text.SeparatorOptions;


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

    public final static String PARAM_PREFIX = "param_";
    public final static String DEFVAL_PREFIX = "defval-";
    private final BdfServer bdfServer;
    private final PermissionSummary permissionSummary;
    private final FormSyntax.Parameters ficheItemFormSyntaxParameters;
    private final FicheblockSyntax.Parameters ficheBlockFormSyntaxParameters;
    private final Map<String, String> supplementaryParameterMap = new HashMap<String, String>();
    private final Map<String, String> customDefaultValueMap = new HashMap<String, String>();
    private UserLangContext userLangContext;
    private SubsetItem masterSubsetItem;
    private Redacteur defaultRedacteur;
    private SeparatorOptions inlineSeparatorOptions = FormSyntax.DEFAULT_INLINE_SEPARATOROPTIONS;
    private SeparatorOptions blockSeparatorOptions = FormSyntax.DEFAULT_BLOCK_SEPARATOROPTIONS;

    private FicheFormParametersBuilder(BdfServer bdfServer, UserLangContext userLangContext, PermissionSummary permissionSummary, FormSyntax.Parameters ficheItemFormSyntaxParameters, FicheblockSyntax.Parameters ficheBlockFormSyntaxParameters) {
        this.bdfServer = bdfServer;
        this.userLangContext = userLangContext;
        this.permissionSummary = permissionSummary;
        this.ficheItemFormSyntaxParameters = ficheItemFormSyntaxParameters;
        this.ficheBlockFormSyntaxParameters = ficheBlockFormSyntaxParameters;
    }

    public FicheFormParametersBuilder setUserLangContext(UserLangContext userLangContext) {
        if (userLangContext == null) {
            throw new IllegalArgumentException("userLangContext is null");
        }
        this.userLangContext = userLangContext;
        ficheItemFormSyntaxParameters.decimalChar((new DecimalFormatSymbols(userLangContext.getFormatLocale())).getDecimalSeparator());
        return this;
    }

    public FicheFormParametersBuilder setDefaultRedacteur(Redacteur defaultRedacteur) {
        this.defaultRedacteur = defaultRedacteur;
        return this;
    }

    public FicheFormParametersBuilder setInlineSeparatorOptions(SeparatorOptions inlineSeparatorOptions) {
        if (inlineSeparatorOptions == null) {
            this.inlineSeparatorOptions = FormSyntax.DEFAULT_INLINE_SEPARATOROPTIONS;
        } else {
            this.inlineSeparatorOptions = inlineSeparatorOptions;
        }
        return this;
    }


    public FicheFormParametersBuilder setBlockSeparatorOptions(SeparatorOptions blockSeparatorOptions) {
        if (blockSeparatorOptions == null) {
            this.blockSeparatorOptions = FormSyntax.DEFAULT_BLOCK_SEPARATOROPTIONS;
        } else {
            this.blockSeparatorOptions = blockSeparatorOptions;
        }
        return this;
    }

    public FicheFormParametersBuilder setWithSpecialParseChars(boolean withSpecialParseChars) {
        ficheBlockFormSyntaxParameters.withSpecialParseChars(withSpecialParseChars);
        return this;
    }


    public FicheFormParametersBuilder setMasterSubsetItem(SubsetItem masterSubsetItem) {
        this.masterSubsetItem = masterSubsetItem;
        return this;
    }

    public FicheFormParametersBuilder populateFromRequest(RequestMap requestMap) {
        for (String name : requestMap.getParameterNameSet()) {
            if (name.startsWith(PARAM_PREFIX)) {
                String subname = name.substring(PARAM_PREFIX.length());
                String value = requestMap.getParameter(name);
                supplementaryParameterMap.put(subname, value);
            } else if (name.startsWith(DEFVAL_PREFIX)) {
                String componentName = name.substring(DEFVAL_PREFIX.length());
                String defaultValue = requestMap.getParameter(name);
                customDefaultValueMap.put(componentName, defaultValue);
            }
        }
        return this;
    }

    public FicheFormParametersBuilder setCustomDefaultValue(String componentName, String defaultValue) {
        customDefaultValueMap.put(componentName, defaultValue);
        return this;
    }

    public static FicheFormParametersBuilder build(BdfParameters bdfParameters) {
        return build(bdfParameters.getBdfServer(), bdfParameters.getBdfUser(), bdfParameters.getPermissionSummary());
    }

    public static FicheFormParametersBuilder build(BdfServer bdfServer, BdfUser bdfUser) {
        return build(bdfServer, bdfUser, PermissionSummaryBuilder.build(bdfServer, bdfUser));
    }

    public static FicheFormParametersBuilder build(BdfServer bdfServer, BdfUser bdfUser, PermissionSummary permissionSummary) {
        FormSyntax.Parameters ficheItemFormSyntaxParameters = FormSyntax.parameters()
                .defautSphereKey(bdfUser.getRedacteur().getSubsetKey())
                .decimalChar((new DecimalFormatSymbols(bdfUser.getFormatLocale())).getDecimalSeparator());
        FicheblockSyntax.Parameters ficheBlockFormSyntaxParameters = FicheblockSyntax.parameters().withSpecialParseChars(true);
        FicheFormParametersBuilder ficheFormParametersBuilder = new FicheFormParametersBuilder(bdfServer, bdfUser, permissionSummary, ficheItemFormSyntaxParameters, ficheBlockFormSyntaxParameters);
        return ficheFormParametersBuilder
                .setDefaultRedacteur(bdfUser.getRedacteur());
    }


    public FicheFormParameters toFicheFormParameters() {
        return new InternalFicheFormParameters(bdfServer, userLangContext, permissionSummary,
                ficheItemFormSyntaxParameters, ficheBlockFormSyntaxParameters, supplementaryParameterMap, customDefaultValueMap, masterSubsetItem, defaultRedacteur,
                inlineSeparatorOptions, blockSeparatorOptions);
    }


    private static class InternalFicheFormParameters implements FicheFormParameters {

        private final BdfServer bdfServer;
        private final PermissionSummary permissionSummary;
        private final FormSyntax.Parameters ficheItemFormSyntaxParameters;
        private final FicheblockSyntax.Parameters ficheBlockFormSyntaxParameters;
        private final Map<String, String> supplementaryParameterMap;
        private final Map<String, String> customDefaultValueMap;
        private final UserLangContext userLangContext;
        private final SubsetItem masterSubsetItem;
        private final Redacteur defaultRedacteur;
        private final SeparatorOptions inlineSeparatorOptions;
        private final SeparatorOptions blockSeparatorOptions;

        private InternalFicheFormParameters(BdfServer bdfServer, UserLangContext userLangContext, PermissionSummary permissionSummary, FormSyntax.Parameters ficheItemFormSyntaxParameters, FicheblockSyntax.Parameters ficheBlockFormSyntaxParameters,
                Map<String, String> supplementaryParameterMap, Map<String, String> customDefaultValueMap, SubsetItem masterSubsetItem, Redacteur defaultRedacteur, SeparatorOptions inlineSeparatorOptions, SeparatorOptions blockSeparatorOptions) {
            this.bdfServer = bdfServer;
            this.userLangContext = userLangContext;
            this.permissionSummary = permissionSummary;
            this.ficheItemFormSyntaxParameters = ficheItemFormSyntaxParameters;
            this.ficheBlockFormSyntaxParameters = ficheBlockFormSyntaxParameters;
            this.supplementaryParameterMap = supplementaryParameterMap;
            this.customDefaultValueMap = customDefaultValueMap;
            this.masterSubsetItem = masterSubsetItem;
            this.defaultRedacteur = defaultRedacteur;
            this.inlineSeparatorOptions = inlineSeparatorOptions;
            this.blockSeparatorOptions = blockSeparatorOptions;
        }

        @Override
        public BdfServer getBdfServer() {
            return bdfServer;
        }

        @Override
        public PermissionSummary getPermissionSummary() {
            return permissionSummary;
        }

        @Override
        public UserLangContext getUserLangContext() {
            return userLangContext;
        }

        @Override
        public String getSupplementaryParameter(String name) {
            return supplementaryParameterMap.get(name);
        }

        @Override
        public String getCustomDefaultValue(String componentName) {
            return customDefaultValueMap.get(componentName);
        }

        @Override
        public FormSyntax.Parameters getFicheItemFormSyntaxParameters() {
            return ficheItemFormSyntaxParameters;
        }

        @Override
        public FicheblockSyntax.Parameters getFicheBlockFormSyntaxParameters() {
            return ficheBlockFormSyntaxParameters;
        }

        @Override
        public Redacteur getDefaultRedacteur() {
            return defaultRedacteur;
        }

        @Override
        public SeparatorOptions getBlockSeparatorOptions() {
            return blockSeparatorOptions;
        }

        @Override
        public SubsetItem getMasterSubsetItem() {
            return masterSubsetItem;
        }

        @Override
        public SeparatorOptions getInlineSeparatorOptions() {
            return inlineSeparatorOptions;
        }

    }

}
