/* BdfServer_Commands - Copyright (c) 2012-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 fr.exemole.bdfserver.commands.administration;

import fr.exemole.bdfserver.api.BdfServer;
import fr.exemole.bdfserver.api.BdfServerEditor;
import fr.exemole.bdfserver.api.EditSession;
import fr.exemole.bdfserver.api.interaction.Domains;
import fr.exemole.bdfserver.api.roles.FichePermission;
import fr.exemole.bdfserver.api.roles.Permission;
import fr.exemole.bdfserver.api.roles.Role;
import fr.exemole.bdfserver.api.roles.RoleEditor;
import fr.exemole.bdfserver.tools.BdfServerUtils;
import fr.exemole.bdfserver.tools.instruction.AbstractBdfCommand;
import fr.exemole.bdfserver.tools.instruction.BdfErrors;
import fr.exemole.bdfserver.tools.roles.RoleUtils;
import java.text.ParseException;
import java.util.HashMap;
import java.util.Map;
import net.fichotheque.Subset;
import net.fichotheque.SubsetKey;
import net.fichotheque.utils.FichothequeUtils;
import net.mapeadores.util.attr.AttributeChange;
import net.mapeadores.util.attr.AttributeParser;
import net.mapeadores.util.logging.ErrorMessageException;
import net.mapeadores.util.request.RequestMap;
import net.mapeadores.util.text.LabelChange;


/**
 *
 * @author Vincent Calame
 */
public class RoleChangeCommand extends AbstractBdfCommand {

    public final static String COMMANDNAME = "RoleChange";
    public final static String COMMANDKEY = "_ ROL-02";
    public final static String PERMISSION_PARAMNAME = "permission";
    public final static String LEVEL_PARAMSUFFIX = "|level";
    public final static String CREATEFICHE_PARAMSUFFIX = "|createfiche";
    public final static String READFICHE_PARAMSUFFIX = "|readfiche";
    public final static String WRITEFICHE_PARAMSUFFIX = "|writefiche";
    public final static String TITLE_PARAMPREFIX = "title/";
    public final static String ATTRIBUTES_PARAMNAME = "attributes";
    private Role role;
    private LabelChange labelChange;
    private AttributeChange attributeChange;
    private final Map<SubsetKey, Permission> permissionMap = new HashMap<SubsetKey, Permission>();

    public RoleChangeCommand(BdfServer bdfServer, RequestMap requestMap) {
        super(bdfServer, requestMap);
    }

    @Override
    public boolean needSynchronisation() {
        return true;
    }

    @Override
    protected void doCommand() {
        try (EditSession session = startEditSession(Domains.ADMINISTRATION, COMMANDNAME)) {
            BdfServerEditor bdfServerEditor = session.getBdfServerEditor();
            RoleEditor roleEditor = bdfServerEditor.getRoleEditor();
            BdfServerUtils.changeLabels(bdfServerEditor, role, labelChange);
            if (attributeChange != null) {
                BdfServerUtils.changeAttributes(bdfServerEditor, role, attributeChange);
            }
            Subset[] subsetArray = FichothequeUtils.toSubsetArray(fichotheque);
            for (Subset subset : subsetArray) {
                SubsetKey subsetKey = subset.getSubsetKey();
                Permission permission = permissionMap.get(subsetKey);
                if (permission != null) {
                    roleEditor.putSubsetPermission(role, subsetKey, permission);
                } else {
                    roleEditor.removeSubsetPermission(role, subsetKey);
                }
            }
        }
        setDone("_ done.administration.rolechange");
        putResultObject(ROLE_OBJ, role);
    }


    @Override
    protected void checkParameters() throws ErrorMessageException {
        checkFichothequeAdmin();
        role = requestHandler.getMandatoryRole();
        labelChange = requestHandler.getLabelChange(TITLE_PARAMPREFIX);
        String[] permissionArray = requestHandler.getTokens(PERMISSION_PARAMNAME);
        for (String permission : permissionArray) {
            try {
                SubsetKey subsetKey = SubsetKey.parse(permission);
                initSubsetPermission(subsetKey);
            } catch (ParseException pe) {
                throw BdfErrors.wrongParameterValue(PERMISSION_PARAMNAME, permission);
            }
        }
        String attributes = requestHandler.getTrimedParameter(ATTRIBUTES_PARAMNAME);
        if (!attributes.isEmpty()) {
            attributeChange = AttributeParser.parse(attributes);
        }
    }

    private void initSubsetPermission(SubsetKey subsetKey) throws ErrorMessageException {
        String levelParamName = subsetKey + LEVEL_PARAMSUFFIX;
        String levelString = getMandatory(levelParamName);
        short level;
        Permission.CustomPermission customPermission = null;
        try {
            level = RoleUtils.levelToShort(levelString);
        } catch (IllegalArgumentException iae) {
            throw BdfErrors.wrongParameterValue(levelParamName, levelString);
        }
        if ((level == Permission.CUSTOM_LEVEL) && (subsetKey.isCorpusSubset())) {
            boolean create = requestHandler.isTrue(subsetKey + CREATEFICHE_PARAMSUFFIX);
            short read = getType(subsetKey + READFICHE_PARAMSUFFIX);
            short write = getType(subsetKey + WRITEFICHE_PARAMSUFFIX);
            FichePermission fichePermission = RoleUtils.toFichePermission(create, read, write);
            if (RoleUtils.matchStandardPermission(fichePermission)) {
                level = Permission.STANDARD_LEVEL;
            } else {
                customPermission = fichePermission;
            }
        }
        permissionMap.put(subsetKey, RoleUtils.toPermission(level, customPermission));
    }

    private short getType(String paramName) throws ErrorMessageException {
        String fichePermissionString = requestHandler.getTrimedParameter(paramName);
        if (fichePermissionString.isEmpty()) {
            throw BdfErrors.emptyMandatoryParameter(paramName);
        }
        try {
            short type = RoleUtils.fichePermissionTypeToShort(fichePermissionString);
            return type;
        } catch (IllegalArgumentException iae) {
            throw BdfErrors.wrongParameterValue(paramName, fichePermissionString);
        }
    }

}
