/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.jackrabbit.oak.security.user;

import com.google.common.base.Stopwatch;
import com.google.common.base.Strings;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import org.apache.jackrabbit.api.security.user.Authorizable;
import org.apache.jackrabbit.api.security.user.Group;
import org.apache.jackrabbit.api.security.user.UserManager;
import org.apache.jackrabbit.commons.iterator.RangeIteratorAdapter;
import org.apache.jackrabbit.oak.api.Tree;
import org.apache.jackrabbit.oak.spi.security.user.AuthorizableType;
import org.apache.jackrabbit.oak.spi.security.user.DynamicMembershipProvider;
import org.apache.jackrabbit.oak.spi.security.user.util.UserUtil;
import org.apache.jackrabbit.oak.spi.xml.ImportBehavior;
import org.jetbrains.annotations.NotNull;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.jcr.RepositoryException;
import javax.jcr.nodetype.ConstraintViolationException;
import java.security.Principal;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

import static java.util.concurrent.TimeUnit.NANOSECONDS;

/**
 * GroupImpl...
 */
class GroupImpl extends AuthorizableImpl implements Group {

    private static final Logger log = LoggerFactory.getLogger(GroupImpl.class);

    GroupImpl(String id, Tree tree, UserManagerImpl userManager) throws RepositoryException {
        super(id, tree, userManager);
    }

    //---------------------------------------------------< AuthorizableImpl >---
    @Override
    void checkValidTree(@NotNull Tree tree) {
        if (!UserUtil.isType(tree, AuthorizableType.GROUP)) {
            throw new IllegalArgumentException("Invalid group node: node type rep:Group expected.");
        }
    }

    //-------------------------------------------------------< Authorizable >---
    @Override
    public boolean isGroup() {
        return true;
    }

    @NotNull
    @Override
    public Principal getPrincipal() throws RepositoryException {
        return new GroupPrincipal(getPrincipalName(), getTree());
    }

    //--------------------------------------------------------------< Group >---
    @NotNull
    @Override
    public Iterator<Authorizable> getDeclaredMembers() throws RepositoryException {
        return getMembersMonitored(false);
    }

    @NotNull
    @Override
    public Iterator<Authorizable> getMembers() throws RepositoryException {
        return getMembersMonitored(true);
    }

    @Override
    public boolean isDeclaredMember(@NotNull Authorizable authorizable) throws RepositoryException {
        return isMember(authorizable, false);
    }

    @Override
    public boolean isMember(@NotNull Authorizable authorizable) throws RepositoryException {
        return isMember(authorizable, true);
    }

    @Override
    public boolean addMember(@NotNull Authorizable authorizable) throws RepositoryException {
        Stopwatch watch = Stopwatch.createStarted();
        boolean success = internalAddMember(authorizable);
        getMonitor().doneUpdateMembers(watch.elapsed(NANOSECONDS), 1, (success) ? 0 : 1, false);
        return success;
    }

    private boolean internalAddMember(@NotNull Authorizable authorizable) throws RepositoryException {
        if (!isValidAuthorizableImpl(authorizable)) {
            log.warn("Invalid Authorizable: {}", authorizable);
            return false;
        }

        DynamicMembershipProvider dmp = getUserManager().getDynamicMembershipProvider();
        if (dmp.coversAllMembers(this)) {
            log.debug("Attempt to add member to dynamic group {}", getID());
            return false;
        }
        AuthorizableImpl authorizableImpl = ((AuthorizableImpl) authorizable);
        if (authorizableImpl.isEveryone()) {
            log.debug("Attempt to create membership for everyone group.");
            return false;
        }

        String memberID = authorizable.getID();
        if (authorizableImpl.isGroup()) {
            if (getID().equals(memberID)) {
                String msg = "Attempt to add a group as member of itself (" + getID() + ").";
                log.debug(msg);
                return false;
            }
            if (isCyclicMembership((Group) authorizable)) {
                String msg = "Cyclic group membership detected for group " + getID() + " and member " + authorizable.getID();
                throw new ConstraintViolationException(msg);
            }
        }

        boolean success = getMembershipProvider().addMember(getTree(), authorizableImpl.getTree());

        if (success) {
            getUserManager().onGroupUpdate(this, false, authorizable);
        }

        return success;
    }

    @NotNull
    @Override
    public Set<String> addMembers(@NotNull String... memberIds) throws RepositoryException {
        return updateMembersMonitored(false, memberIds);
    }

    @Override
    public boolean removeMember(@NotNull Authorizable authorizable) throws RepositoryException {
        Stopwatch watch = Stopwatch.createStarted();
        boolean success = internalRemoveMember(authorizable);
        getMonitor().doneUpdateMembers(watch.elapsed(NANOSECONDS), 1, (success) ? 0 : 1, true);
        return success;
    }

    private boolean internalRemoveMember(@NotNull Authorizable authorizable) throws RepositoryException {
        if (!isValidAuthorizableImpl(authorizable)) {
            log.warn("Invalid Authorizable: {}", authorizable);
            return false;
        }

        DynamicMembershipProvider dmp = getUserManager().getDynamicMembershipProvider();
        if (dmp.coversAllMembers(this)) {
            log.debug("Attempt to remove member from dynamic group {}", getID());
            return false;
        }
        
        AuthorizableImpl authorizableImpl = ((AuthorizableImpl) authorizable);
        if (authorizableImpl.isEveryone()) {
            log.debug("Attempt to remove membership for everyone group.");
            return false;
        } else {
            Tree memberTree = authorizableImpl.getTree();
            boolean success = getMembershipProvider().removeMember(getTree(), memberTree);
            if (success) {
                getUserManager().onGroupUpdate(this, true, authorizable);
            }
            return success;
        }
    }

    @NotNull
    @Override
    public Set<String> removeMembers(@NotNull String... memberIds) throws RepositoryException {
        return updateMembersMonitored(true, memberIds);
    }

    //--------------------------------------------------------------------------
    @NotNull
    private Iterator<Authorizable> getMembersMonitored(boolean includeInherited) throws RepositoryException {
        Stopwatch watch = Stopwatch.createStarted();
        Iterator<Authorizable> members = getMembers(includeInherited);
        getMonitor().doneGetMembers(watch.elapsed(NANOSECONDS), !includeInherited);
        return members;
    }

    /**
     * Internal implementation of {@link #getDeclaredMembers()} and {@link #getMembers()}.
     *
     * @param includeInherited Flag indicating if only the declared or all members
     * should be returned.
     * @return Iterator of authorizables being member of this group.
     * @throws RepositoryException If an error occurs.
     */
    @NotNull
    private Iterator<Authorizable> getMembers(boolean includeInherited) throws RepositoryException {
        UserManagerImpl userMgr = getUserManager();

        DynamicMembershipProvider dmp = getUserManager().getDynamicMembershipProvider();
        Iterator<Authorizable> dynamicMembers = dmp.getMembers(this, includeInherited);
        if (dmp.coversAllMembers(this)) {
            return AuthorizableIterator.create(true, dynamicMembers, AuthorizableIterator.empty());
        }

        // dynamic membership didn't cover all members -> extract from group-tree
        Iterator<Tree> trees = getMembershipProvider().getMembers(getTree(), includeInherited);
        if (!trees.hasNext()) {
            return AuthorizableIterator.create(true, dynamicMembers, AuthorizableIterator.empty());
        }
        
        Iterator<Authorizable> members = AuthorizableIterator.create(trees, userMgr, AuthorizableType.AUTHORIZABLE);
        if (includeInherited) {
            // need to resolve dynamic members of declared and inherited group-members 
            members = new InheritedMembersIterator(members, dmp);
        }
        AuthorizableIterator allMembers = AuthorizableIterator.create(true, dynamicMembers, members);
        return new RangeIteratorAdapter(allMembers, allMembers.getSize()); 
    }

    /**
     * Internal implementation of {@link #isDeclaredMember(Authorizable)} and {@link #isMember(Authorizable)}.
     *
     * @param authorizable The authorizable to test.
     * @param includeInherited Flag indicating if only declared or all members
     * should taken into account.
     * @return {@code true} if the specified authorizable is member or declared
     * member of this group; {@code false} otherwise.
     * @throws RepositoryException If an error occurs.
     */
    private boolean isMember(@NotNull Authorizable authorizable, boolean includeInherited) throws RepositoryException {
        if (!isValidAuthorizableImpl(authorizable)) {
            return false;
        }
        if (getID().equals(authorizable.getID()) || ((AuthorizableImpl) authorizable).isEveryone()) {
            return false;
        }

        DynamicMembershipProvider dmp = getUserManager().getDynamicMembershipProvider();
        if (dmp.isMember(this, authorizable, includeInherited)) {
            return true;
        }

        // no dynamic membership -> regular membership provider needs to evaluate
        Tree authorizableTree = ((AuthorizableImpl) authorizable).getTree();
        MembershipProvider mgr = getUserManager().getMembershipProvider();
        if (includeInherited) {
            return mgr.isMember(this.getTree(), authorizableTree);
        } else {
            return mgr.isDeclaredMember(this.getTree(), authorizableTree);
        }
    }

    @NotNull
    private Set<String> updateMembersMonitored(boolean isRemove, @NotNull String... memberIds) throws RepositoryException {
        Stopwatch watch = Stopwatch.createStarted();
        Set<String> failed = updateMembers(isRemove, memberIds);
        getMonitor().doneUpdateMembers(watch.elapsed(NANOSECONDS), memberIds.length, failed.size(), isRemove);
        return failed;
    }

    /**
     * Internal method to add or remove members by ID.
     *
     * @param isRemove Boolean flag indicating if members should be added or removed.
     * @param memberIds The {@code memberIds} to be added or removed.
     * @return The sub-set of {@code memberIds} that could not be added/removed.
     * @throws javax.jcr.nodetype.ConstraintViolationException If any of the specified
     * IDs is empty string or null or if {@link org.apache.jackrabbit.oak.spi.xml.ImportBehavior#ABORT}
     * is configured and an ID cannot be resolved to an existing (or accessible)
     * authorizable.
     * @throws javax.jcr.RepositoryException If another error occurs.
     */
    @NotNull
    private Set<String> updateMembers(boolean isRemove, @NotNull String... memberIds) throws RepositoryException {
        Set<String> failedIds = Sets.newHashSet(memberIds);
        int importBehavior = UserUtil.getImportBehavior(getUserManager().getConfig());

        DynamicMembershipProvider dmp = getUserManager().getDynamicMembershipProvider();
        if (dmp.coversAllMembers(this)) {
            String msg = "Attempt to add to or remove from dynamic group {}.";
            log.debug(msg, getID());
            return failedIds;
        }

        // calculate the contentID for each memberId and remember ids that cannot be processed
        Map<String, String> updateMap = Maps.newHashMapWithExpectedSize(memberIds.length);
        MembershipProvider mp = getMembershipProvider();
        for (String memberId : memberIds) {
            if (Strings.isNullOrEmpty(memberId)) {
                throw new ConstraintViolationException("MemberId must not be null or empty.");
            }
            if (isValidMemberId(memberId, importBehavior)) {
                // memberId can be processed -> remove from failedIds and generate contentID
                failedIds.remove(memberId);
                updateMap.put(mp.getContentID(memberId), memberId);
            }
        }

        Set<String> processedIds = Sets.newHashSet(updateMap.values());
        if (!updateMap.isEmpty()) {
            Set<String> result;
            if (isRemove) {
                result = mp.removeMembers(getTree(), updateMap);
            } else {
                result = mp.addMembers(getTree(), updateMap);
            }
            failedIds.addAll(result);
            processedIds.removeAll(result);
        }

        getUserManager().onGroupUpdate(this, isRemove, false, processedIds, failedIds);
        return failedIds;
    }

    private boolean isValidMemberId(@NotNull String memberId, int importBehavior) throws RepositoryException {
        if (getID().equals(memberId)) {
            log.debug("Attempt to add or remove a group as member of itself ({}).", getID());
            return false;
        }

        if (ImportBehavior.BESTEFFORT != importBehavior) {
            Authorizable member = getUserManager().getAuthorizable(memberId);
            String msg = null;
            if (member == null) {
                msg = "Attempt to add or remove a non-existing member '" + memberId + "' with ImportBehavior = " + ImportBehavior.nameFromValue(importBehavior);
            } else if (member.isGroup()) {
                if (((AuthorizableImpl) member).isEveryone()) {
                    log.debug("Attempt to add everyone group as member.");
                    return false;
                } else if (isCyclicMembership((Group) member)) {
                    msg = "Cyclic group membership detected for group " + getID() + " and member " + member.getID();
                }
            }
            if (msg != null) {
                if (ImportBehavior.ABORT == importBehavior) {
                    throw new ConstraintViolationException(msg);
                } else {
                    // ImportBehavior.IGNORE is default in UserUtil.getImportBehavior
                    log.debug(msg);
                    return false;
                }
            }
        }
        return true;
    }

    private boolean isCyclicMembership(@NotNull Group member) throws RepositoryException {
        return member.isMember(this);
    }

    /**
     * Principal representation of this group instance.
     */
    private final class GroupPrincipal extends AbstractGroupPrincipal {

        private GroupPrincipal(String principalName, Tree groupTree) {
            super(principalName, groupTree, GroupImpl.this.getUserManager().getNamePathMapper());
        }

        @Override
        UserManager getUserManager() {
            return GroupImpl.this.getUserManager();
        }

        @Override
        boolean isEveryone() {
            return GroupImpl.this.isEveryone();
        }

        @Override
        boolean isMember(@NotNull Authorizable authorizable) throws RepositoryException {
            return GroupImpl.this.isMember(authorizable);
        }

        @NotNull
        @Override
        Iterator<Authorizable> getMembers() throws RepositoryException {
            return GroupImpl.this.getMembers();
        }
    }
}
