/* BdfServer - Copyright (c) 2008-2018 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.impl;

import fr.exemole.bdfserver.api.roles.Permission;
import fr.exemole.bdfserver.api.roles.Role;
import fr.exemole.bdfserver.api.roles.RoleDef;
import fr.exemole.bdfserver.tools.roles.RoleUtils;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import net.fichotheque.SubsetKey;
import net.mapeadores.util.attr.Attribute;
import net.mapeadores.util.attr.AttributeKey;
import net.mapeadores.util.attr.Attributes;
import net.mapeadores.util.attr.AttributesCache;
import net.mapeadores.util.localisation.Lang;
import net.mapeadores.util.text.Label;
import net.mapeadores.util.text.Labels;
import net.mapeadores.util.text.LabelsCache;


/**
 *
 * @author Vincent Calame
 */
class RoleImpl implements Role {

    private final String name;
    private final boolean isDefault;
    private final LabelsCache labelsCache = new LabelsCache();
    private final AttributesCache attributesCache = new AttributesCache();
    private final Map<SubsetKey, Permission> subsetPermissionMap = new LinkedHashMap<SubsetKey, Permission>();
    private List<RoleDef.SubsetEntry> cacheList;

    private RoleImpl(String name) {
        this.name = name;
        this.isDefault = (name.equals(Role.DEFAULT_ROLE));
    }

    @Override
    public Permission getPermissionBySubsetKey(SubsetKey subsetKey) {
        return subsetPermissionMap.get(subsetKey);
    }

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

    @Override
    public List<SubsetEntry> getSubsetEntryList() {
        List<RoleDef.SubsetEntry> result = cacheList;
        if (result == null) {
            result = initSubsetEntryList();
        }
        return result;
    }

    @Override
    public Labels getTitleLabels() {
        return labelsCache.getLabels();
    }

    @Override
    public Attributes getAttributes() {
        return attributesCache.getAttributes();
    }

    void putSubsetPermission(SubsetKey subsetKey, Permission permission) {
        if (isDefault) {
            if (permission.getLevel() == Permission.STANDARD_LEVEL) {
                removeSubsetPermission(subsetKey);
                return;
            }
        } else {
            if (permission.getLevel() == Permission.NONE_LEVEL) {
                removeSubsetPermission(subsetKey);
                return;
            }
        }
        subsetPermissionMap.put(subsetKey, permission);
        clearCache();
    }

    void removeSubsetPermission(SubsetKey subsetKey) {
        subsetPermissionMap.remove(subsetKey);
        clearCache();
    }

    private synchronized List<SubsetEntry> initSubsetEntryList() {
        if (cacheList != null) {
            return cacheList;
        }
        List<SubsetEntry> tempList = new ArrayList<SubsetEntry>();
        for (Map.Entry<SubsetKey, Permission> entry : subsetPermissionMap.entrySet()) {
            tempList.add(RoleUtils.toSubsetEntry(entry.getKey(), entry.getValue()));
        }
        List<SubsetEntry> newList = RoleUtils.wrap(tempList.toArray(new SubsetEntry[tempList.size()]));
        cacheList = newList;
        return newList;
    }

    private void clearCache() {
        cacheList = null;
    }

    boolean putLabel(Label label) {
        return labelsCache.putLabel(label);
    }

    boolean removeLabel(Lang lang) {
        return labelsCache.removeLabel(lang);
    }

    boolean removeAttribute(AttributeKey attributeKey) {
        return attributesCache.removeAttribute(attributeKey);
    }

    boolean putAttribute(Attribute attribute) {
        return attributesCache.putAttribute(attribute);
    }

    static RoleImpl fromRoleDef(RoleDef roleDef) {
        RoleImpl role = new RoleImpl(roleDef.getName());
        for (RoleDef.SubsetEntry entry : roleDef.getSubsetEntryList()) {
            role.putSubsetPermission(entry.getSubsetKey(), entry.getPermission());
        }
        role.labelsCache.putLabels(roleDef.getTitleLabels());
        role.attributesCache.putAttributes(roleDef.getAttributes());
        return role;
    }

    static RoleImpl fromName(String roleName) {
        return new RoleImpl(roleName);
    }

}
