/*
 * 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.spi.security.authentication.external.impl;

import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import org.apache.jackrabbit.api.security.principal.ItemBasedPrincipal;
import org.apache.jackrabbit.api.security.principal.PrincipalManager;
import org.apache.jackrabbit.api.security.user.Authorizable;
import org.apache.jackrabbit.api.security.user.Group;
import org.apache.jackrabbit.api.security.user.User;
import org.apache.jackrabbit.oak.api.Tree;
import org.apache.jackrabbit.oak.spi.security.authentication.external.ExternalGroup;
import org.apache.jackrabbit.oak.spi.security.authentication.external.ExternalIdentity;
import org.apache.jackrabbit.oak.spi.security.authentication.external.ExternalIdentityRef;
import org.apache.jackrabbit.oak.spi.security.authentication.external.ExternalUser;
import org.apache.jackrabbit.oak.spi.security.authentication.external.SyncResult;
import org.apache.jackrabbit.oak.spi.security.authentication.external.TestIdentityProvider;
import org.apache.jackrabbit.oak.spi.security.authentication.external.basic.DefaultSyncConfig;
import org.apache.jackrabbit.oak.spi.security.user.UserConstants;
import org.jetbrains.annotations.NotNull;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;

import javax.jcr.RepositoryException;
import java.security.Principal;
import java.util.Arrays;
import java.util.Collection;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;

import static org.apache.jackrabbit.oak.spi.security.authentication.external.impl.ExternalIdentityConstants.REP_EXTERNAL_PRINCIPAL_NAMES;
import static org.apache.jackrabbit.oak.spi.security.user.UserConstants.REP_MEMBERS;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;

@RunWith(Parameterized.class)
public class DynamicGroupsTest extends DynamicSyncContextTest {

    @Parameterized.Parameters(name = "name={1}")
    public static Collection<Object[]> parameters() {
        return Lists.newArrayList(
                new Object[] { DefaultSyncConfigImpl.PARAM_USER_MEMBERSHIP_NESTING_DEPTH_DEFAULT, "Membership-Nesting-Depth=0" },
                new Object[] { DefaultSyncConfigImpl.PARAM_USER_MEMBERSHIP_NESTING_DEPTH_DEFAULT+1, "Membership-Nesting-Depth=1" },
                new Object[] { DefaultSyncConfigImpl.PARAM_USER_MEMBERSHIP_NESTING_DEPTH_DEFAULT+2, "Membership-Nesting-Depth=2" });
    }
    
    private final long membershipNestingDepth;

    public DynamicGroupsTest(long membershipNestingDepth, @NotNull String name) {
        this.membershipNestingDepth = membershipNestingDepth;
    }
    
    @Override
    protected @NotNull DefaultSyncConfig createSyncConfig() {
        DefaultSyncConfig config = super.createSyncConfig();
        config.group().setDynamicGroups(true);
        config.user().setMembershipNestingDepth(membershipNestingDepth);
        return config;
    }

    @Test
    public void testSyncExternalGroup() throws Exception {
        ExternalGroup gr = idp.getGroup(GROUP_ID);
        
        syncContext.sync(gr);
        assertNotNull(userManager.getAuthorizable(gr.getId()));
        assertTrue(r.hasPendingChanges());
    }

    @Test
    public void testSyncExternalUserExistingGroups() throws Exception {
        // verify group membership of the previously synced user
        Authorizable a = userManager.getAuthorizable(previouslySyncedUser.getId());
        assertSyncedMembership(userManager, a, previouslySyncedUser, Long.MAX_VALUE);

        // resync the previously synced user with dynamic-membership enabled.
        syncContext.setForceUserSync(true);
        syncConfig.user().setMembershipExpirationTime(-1);
        syncContext.sync(previouslySyncedUser);

        Tree t = r.getTree(a.getPath());
        
        // dynamic-group option forces migration of previously synced groups
        assertTrue(t.hasProperty(REP_EXTERNAL_PRINCIPAL_NAMES));

        assertSyncedMembership(userManager, a, previouslySyncedUser);
    }

    @Test
    public void testSyncMembershipWithEmptyExistingGroups() throws Exception {
        Authorizable a = userManager.getAuthorizable(PREVIOUS_SYNCED_ID);
        
        // sync user with modified membership => must be reflected
        // 1. empty set of declared groups
        ExternalUser mod = new TestUserWithGroupRefs(previouslySyncedUser, ImmutableSet.of());
        syncContext.syncMembership(mod, a, membershipNestingDepth);

        assertSyncedMembership(userManager, a, mod, membershipNestingDepth);
        Tree t = r.getTree(a.getPath());
        assertTrue(t.hasProperty(REP_EXTERNAL_PRINCIPAL_NAMES));
        assertEquals(0, t.getProperty(REP_EXTERNAL_PRINCIPAL_NAMES).count());
    }

    @Test
    public void testSyncMembershipWithChangedExistingGroups() throws Exception {
        Authorizable a = userManager.getAuthorizable(PREVIOUS_SYNCED_ID);

        // sync user with modified membership => must be reflected
        // 2. set with different groups that defined on IDP
        ExternalUser mod = new TestUserWithGroupRefs(previouslySyncedUser, ImmutableSet.of(
                idp.getGroup("a").getExternalId(),
                idp.getGroup("aa").getExternalId(),
                idp.getGroup("secondGroup").getExternalId()));
        syncContext.syncMembership(mod, a, membershipNestingDepth);

        Tree t = r.getTree(a.getPath());
        assertTrue(t.hasProperty(REP_EXTERNAL_PRINCIPAL_NAMES));

        Set<String> groupIds = getExpectedSyncedGroupIds(membershipNestingDepth, idp, mod);
        assertEquals(groupIds.size(), t.getProperty(REP_EXTERNAL_PRINCIPAL_NAMES).count());
        
        assertMigratedGroups(previouslySyncedUser, t);
        if (membershipNestingDepth == 0) {
            for (String grId : groupIds) {
                assertNull(userManager.getAuthorizable(grId));
            }
        } else {
            assertMigratedGroups(mod, t);
        }
    }

    private void assertMigratedGroups(@NotNull ExternalIdentity externalIdentity, @NotNull Tree userTree) throws Exception {
        for (ExternalIdentityRef ref : externalIdentity.getDeclaredGroups()) {
            Group gr = userManager.getAuthorizable(ref.getId(), Group.class);
            assertNotNull(gr);
            assertFalse(hasStoredMembershipInformation(r.getTree(gr.getPath()), userTree));
        }
    }
    
    @Test
    public void testSyncNewGroup() throws Exception {
        String id = "newGroup";
        TestIdentityProvider.TestGroup gr = new TestIdentityProvider.TestGroup(id, idp.getName());
        TestIdentityProvider testIDP = (TestIdentityProvider) idp;
        testIDP.addGroup(gr);

        sync(gr, SyncResult.Status.ADD);
        assertNotNull(userManager.getAuthorizable(id));
    }
    
    @Test
    public void testReSyncUserMembershipExpired() throws Exception {
        boolean forceSyncGroupPrevious = syncContext.isForceGroupSync();
        boolean forceSyncUserPrevious = syncContext.isForceUserSync();
        long expTimePrevious = syncConfig.user().getMembershipExpirationTime();
        try {
            syncContext.setForceGroupSync(true).setForceUserSync(true);
            syncConfig.user().setMembershipExpirationTime(-1);
            
            // re-sync with dynamic-sync-context and force membership update
            sync(idp.getUser(PREVIOUS_SYNCED_ID), SyncResult.Status.UPDATE);

            // verify that user and groups have been migrated to dynamic membership/group
            User user = userManager.getAuthorizable(PREVIOUS_SYNCED_ID, User.class);
            assertNotNull(user);
            assertTrue(user.hasProperty(REP_EXTERNAL_PRINCIPAL_NAMES));
            Set<String> extPNames = Arrays.stream(user.getProperty(REP_EXTERNAL_PRINCIPAL_NAMES)).filter(Objects::nonNull).map(value -> {
                try {
                    return value.getString();
                } catch (RepositoryException repositoryException) {
                    return "";
                }
            }).collect(Collectors.toSet());
            
            // rep:principalNames are migrated using the current membershipNestingDepth (not the one from previous sync) 
            Set<String> expectedGroupIds = getExpectedSyncedGroupIds(membershipNestingDepth, idp, previouslySyncedUser);
            assertEquals(expectedGroupIds.size(), extPNames.size());

            // group membership must have moved to dynamic membership
            // previously synced membership (with different depth) must be adjusted to new value
            Tree userTree = r.getTree(user.getPath());
            for (String groupId : getExpectedSyncedGroupIds(PREVIOUS_NESTING_DEPTH, idp, previouslySyncedUser)) {
                Group gr = userManager.getAuthorizable(groupId, Group.class);
                // no group must be removed
                assertNotNull(gr);
                
                // with dynamic.group option members must be migrated to dynamic membership even if 'enforce' option is disabled.
                Tree t = r.getTree(gr.getPath());
                assertFalse(hasStoredMembershipInformation(t, userTree));

                boolean stillMember = expectedGroupIds.contains(gr.getID());
                
                // user-group relationship must be covered by the dynamic-membership provider now
                assertEquals(stillMember, gr.isDeclaredMember(user));
                
                // verify that the group principal name is listed in the ext-principal-names property
                assertEquals(stillMember, extPNames.contains(gr.getPrincipal().getName()));
            }
        } finally {
            syncContext.setForceGroupSync(forceSyncGroupPrevious).setForceUserSync(forceSyncUserPrevious);
            syncConfig.user().setMembershipExpirationTime(expTimePrevious);
        }
    }

    @Test
    public void testReSyncGroupCreatedPriorToEnabledDynamic() throws Exception {
        boolean forceSyncPrevious = syncContext.isForceGroupSync();
        String groupId = previouslySyncedUser.getDeclaredGroups().iterator().next().getId();
        try {
            // re-sync with dynamic-sync-context
            syncContext.setForceGroupSync(true);
            sync(idp.getGroup(groupId), SyncResult.Status.UPDATE);

            // NOTE: group membership is NOT touched upon group-sync
            Group gr = userManager.getAuthorizable(groupId, Group.class);
            assertNotNull(gr);

            User user = userManager.getAuthorizable(PREVIOUS_SYNCED_ID, User.class);
            assertNotNull(user);
            // note: previous sync was executed with deep nesting -> current nesting depth doesn't make a difference
            assertTrue(gr.isMember(user));

            // since group-sync does not touch membership information the group members data must still be present 
            // with the group node.
            Tree t = r.getTree(gr.getPath());
            assertTrue(t.hasProperty(REP_MEMBERS));
            assertFalse(t.hasChild(UserConstants.REP_MEMBERS_LIST));
        } finally {
            syncContext.setForceGroupSync(forceSyncPrevious);
        }
    }
    
    @Test
    public void testGroupPrincipalLookup() throws Exception {
        ExternalUser externalUser = idp.getUser(USER_ID);
        sync(externalUser, SyncResult.Status.ADD);

        PrincipalManager principalManager = getPrincipalManager(r);
        for (ExternalIdentityRef ref : getExpectedSyncedGroupRefs(membershipNestingDepth, idp, externalUser)) {
            String principalName = idp.getIdentity(ref).getPrincipalName();
            Principal p = principalManager.getPrincipal(principalName);
            assertNotNull(p);
            // verify that this principal has been returned by the user-principal-provider and not the external-group-principal-provider.
            assertTrue(p instanceof ItemBasedPrincipal);
            
            Authorizable group = userManager.getAuthorizable(p);
            assertNotNull(group);
            assertTrue(group.isGroup());
            assertEquals(ref.getId(), group.getID());
        }
    }
}