/*
 * 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.principal;

import java.security.Principal;
import java.text.ParseException;
import java.util.Collection;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import javax.jcr.PropertyType;
import javax.jcr.RepositoryException;
import javax.jcr.Value;
import javax.jcr.query.Query;

import com.google.common.base.Predicates;
import com.google.common.base.Strings;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.common.collect.Iterators;
import com.google.common.collect.Sets;

import org.apache.jackrabbit.api.security.principal.GroupPrincipal;
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.UserManager;
import org.apache.jackrabbit.commons.iterator.AbstractLazyIterator;
import org.apache.jackrabbit.oak.api.PropertyState;
import org.apache.jackrabbit.oak.api.PropertyValue;
import org.apache.jackrabbit.oak.api.QueryEngine;
import org.apache.jackrabbit.oak.api.Result;
import org.apache.jackrabbit.oak.api.ResultRow;
import org.apache.jackrabbit.oak.api.Root;
import org.apache.jackrabbit.oak.api.Tree;
import org.apache.jackrabbit.oak.api.Type;
import org.apache.jackrabbit.oak.namepath.NamePathMapper;
import org.apache.jackrabbit.oak.plugins.memory.PropertyValues;
import org.apache.jackrabbit.oak.spi.security.authentication.external.ExternalIdentityRef;
import org.apache.jackrabbit.oak.spi.security.authentication.external.basic.DefaultSyncConfig;
import org.apache.jackrabbit.oak.spi.security.authentication.external.impl.ExternalIdentityConstants;
import org.apache.jackrabbit.oak.spi.security.principal.GroupPrincipals;
import org.apache.jackrabbit.oak.spi.security.principal.PrincipalImpl;
import org.apache.jackrabbit.oak.spi.security.principal.PrincipalProvider;
import org.apache.jackrabbit.oak.spi.security.user.AuthorizableType;
import org.apache.jackrabbit.oak.spi.security.user.UserConfiguration;
import org.apache.jackrabbit.oak.spi.security.user.util.UserUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Implementation of the {@code PrincipalProvider} interface that exposes
 * 'external' principals of type {@link org.apache.jackrabbit.oak.spi.security.principal.GroupPrincipal}. 'External'
 * refers to the fact that these principals are defined and managed by an
 * {@link org.apache.jackrabbit.oak.spi.security.authentication.external.ExternalIdentityProvider}.
 *
 * For performance reasons this implementation doesn't lookup principals on the IDP
 * but relies on a persisted cache inside the repository where the names of these
 * external principals are synchronized to based on a configurable expiration time.
 *
 * Currently, the implementation respects the {@code rep:externalPrincipalNames}
 * properties, where group membership of external users gets synchronized if
 * {@link DefaultSyncConfig.User#getDynamicMembership() dynamic membership} has
 * been enabled.
 *
 * Please note that in contrast to the default principal provider implementation
 * shipped with Oak the group principals known and exposed by this provider are
 * not backed by an authorizable group and thus cannot be retrieved using
 * Jackrabbit user management API.
 *
 * @since Oak 1.5.3
 * @see org.apache.jackrabbit.oak.spi.security.authentication.external.impl.DynamicSyncContext
 */
class ExternalGroupPrincipalProvider implements PrincipalProvider, ExternalIdentityConstants {

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

    private static final String BINDING_PRINCIPAL_NAMES = "principalNames";

    private final Root root;
    private final NamePathMapper namePathMapper;

    private final UserManager userManager;
    private final AutoMembershipPrincipals autoMembershipPrincipals;

    ExternalGroupPrincipalProvider(@NotNull Root root, @NotNull UserConfiguration uc,
                                   @NotNull NamePathMapper namePathMapper,
                                   @NotNull Map<String, String[]> autoMembershipMapping) {
        this.root = root;
        this.namePathMapper = namePathMapper;

        userManager = uc.getUserManager(root, namePathMapper);
        autoMembershipPrincipals = new AutoMembershipPrincipals(autoMembershipMapping);
    }

    //--------------------------------------------------< PrincipalProvider >---
    @Override
    public Principal getPrincipal(@NotNull String principalName) {
        Result result = findPrincipals(principalName, true);
        if (result != null && result.getRows().iterator().hasNext()) {
            return new ExternalGroupPrincipal(principalName);
        } else {
            return null;
        }
    }

    @NotNull
    @Override
    public Set<Principal> getMembershipPrincipals(@NotNull Principal principal) {
        if (!GroupPrincipals.isGroup(principal)) {
            try {
                if (principal instanceof ItemBasedPrincipal) {
                    Tree t = root.getTree(((ItemBasedPrincipal) principal).getPath());
                    return getGroupPrincipals(t);
                } else {
                    return getGroupPrincipals(userManager.getAuthorizable(principal));
                }
            } catch (RepositoryException e) {
                log.debug(e.getMessage());
            }

        }
        return ImmutableSet.of();
    }

    @NotNull
    @Override
    public Set<? extends Principal> getPrincipals(@NotNull String userID) {
        try {
            return getGroupPrincipals(userManager.getAuthorizable(userID));
        } catch (RepositoryException e) {
            log.debug(e.getMessage());
            return ImmutableSet.of();
        }
    }

    @NotNull
    @Override
    public Iterator<? extends Principal> findPrincipals(@Nullable String nameHint, int searchType) {
        if (PrincipalManager.SEARCH_TYPE_NOT_GROUP != searchType) {
            Result result = findPrincipals(Strings.nullToEmpty(nameHint), false);
            if (result != null) {
                return Iterators.filter(new GroupPrincipalIterator(nameHint, result), Predicates.notNull());
            }
        }

        return Collections.emptyIterator();
    }

    @NotNull
    @Override
    public Iterator<? extends Principal> findPrincipals(int searchType) {
        return findPrincipals(null, searchType);
    }

    //------------------------------------------------------------< private >---
    @Nullable
    private String getIdpName(@NotNull Tree userTree) {
        PropertyState ps = userTree.getProperty(REP_EXTERNAL_ID);
        if (ps != null) {
            return ExternalIdentityRef.fromString(ps.getValue(Type.STRING)).getProviderName();
        } else {
            return null;
        }
    }

    private Set<Principal> getGroupPrincipals(@Nullable Authorizable authorizable) throws RepositoryException {
        if (authorizable != null && !authorizable.isGroup()) {
            Tree userTree = root.getTree(authorizable.getPath());
            return getGroupPrincipals(userTree);
        } else {
            return ImmutableSet.of();
        }
    }

    private Set<Principal> getGroupPrincipals(@NotNull Tree userTree) {
        if (userTree.exists() && UserUtil.isType(userTree, AuthorizableType.USER) && userTree.hasProperty(REP_EXTERNAL_PRINCIPAL_NAMES)) {
            PropertyState ps = userTree.getProperty(REP_EXTERNAL_PRINCIPAL_NAMES);
            if (ps != null) {
                // we have an 'external' user that has been synchronized with the dynamic-membership option
                Set<Principal> groupPrincipals = Sets.newHashSet();
                for (String principalName : ps.getValue(Type.STRINGS)) {
                    groupPrincipals.add(new ExternalGroupPrincipal(principalName));
                }

                // add existing group principals as defined with the _autoMembership_ option.
                groupPrincipals.addAll(autoMembershipPrincipals.get(getIdpName(userTree)));
                return groupPrincipals;
            }
        }
        // group principals cannot be retrieved
        return ImmutableSet.of();
    }

    /**
     * Runs an Oak query searching for {@link #REP_EXTERNAL_PRINCIPAL_NAMES} properties
     * that match the given name or name hint.
     *
     * NOTE: ignore any principals listed in the {@link DefaultSyncConfig.User#autoMembership}
     * because they are expected to exist in the system and thus will be found
     * by another principal provider instance.
     *
     * @param nameHint The principal name or name hint to be searched for.
     * @param exactMatch boolean flag indicating if the query should search for
     *                   exact matching.
     * @return The query result.
     */
    @Nullable
    private Result findPrincipals(@NotNull String nameHint, boolean exactMatch) {
        try {
            Map<String, ? extends PropertyValue> bindings = buildBinding(nameHint, exactMatch);
            String op = (exactMatch) ? " = " : " LIKE ";
            String statement = "SELECT '" + REP_EXTERNAL_PRINCIPAL_NAMES + "' FROM [rep:User] WHERE PROPERTY(["
                    + REP_EXTERNAL_PRINCIPAL_NAMES + "], '" + PropertyType.TYPENAME_STRING + "')"
                    + op + "$" + BINDING_PRINCIPAL_NAMES + QueryEngine.INTERNAL_SQL2_QUERY;
            return root.getQueryEngine().executeQuery(statement, Query.JCR_SQL2, bindings, namePathMapper.getSessionLocalMappings());
        } catch (ParseException e) {
            return null;
        }
    }

    /**
     * Build the map used for the query bindings.
     *
     * @param nameHint The name hint
     * @param exactMatch boolean flag indicating if the query should search for exact matching.
     * @return the bindings
     */
    @NotNull
    private static Map<String, ? extends PropertyValue> buildBinding(@NotNull String nameHint, boolean exactMatch) {
        String val = nameHint;
        if (!exactMatch) {
            // not-exact query matching required => add leading and trailing %
            if (nameHint.isEmpty()) {
                val = "%";
            } else {
                StringBuilder sb = new StringBuilder();
                sb.append('%');
                sb.append(nameHint.replace("%", "\\%").replace("_", "\\_"));
                sb.append('%');
                val = sb.toString();
            }
        }
        return Collections.singletonMap(BINDING_PRINCIPAL_NAMES, PropertyValues.newString(val));
    }

    //------------------------------------------------------< inner classes >---

    /**
     * Implementation of the {@link Group} interface representing external group
     * identities that are <strong>not</strong> represented as authorizable group
     * in the repository's user management.
     */
    private final class ExternalGroupPrincipal extends PrincipalImpl implements GroupPrincipal, java.security.acl.Group {

        private ExternalGroupPrincipal(String principalName) {
            super(principalName);

        }

        @Override
        public boolean addMember(Principal user) {
            if (isMember(user)) {
                return false;
            } else {
                throw new UnsupportedOperationException("Adding members to external group principals is not supported.");
            }
        }

        @Override
        public boolean removeMember(Principal user) {
            if (!isMember(user)) {
                return false;
            } else {
                throw new UnsupportedOperationException("Removing members from external group principals is not supported.");
            }
        }

        @Override
        public boolean isMember(Principal member) {
            if (GroupPrincipals.isGroup(member)) {
                return false;
            }
            try {
                String name = getName();
                if (member instanceof ItemBasedPrincipal) {
                    Tree tree = root.getTree(((ItemBasedPrincipal) member).getPath());
                    if (UserUtil.isType(tree, AuthorizableType.USER)) {
                        PropertyState ps = tree.getProperty(REP_EXTERNAL_PRINCIPAL_NAMES);
                        return (ps != null && Iterables.contains(ps.getValue(Type.STRINGS), name));
                    }
                } else {
                    Authorizable a = userManager.getAuthorizable(member);
                    if (a != null && !a.isGroup()) {
                        Value[] vs = a.getProperty(REP_EXTERNAL_PRINCIPAL_NAMES);
                        if (vs != null) {
                            for (Value v : vs) {
                                if (name.equals(v.getString())) {
                                    return true;
                                }
                            }
                        }
                    }
                }
            } catch (RepositoryException e) {
                log.debug(e.getMessage());
            }
            return false;
        }

        @Override
        public Enumeration<? extends Principal> members() {
            Result result = findPrincipals(getName(), true);
            if (result != null) {
                return Iterators.asEnumeration(new MemberIterator(result));
            } else {
                return Iterators.asEnumeration(Collections.<Principal>emptyIterator());
            }
        }
    }

    /**
     * {@link Group} principal iterator converting the query results of
     * {@link #findPrincipals(String, int)} and {@link #findPrincipals(int)}.
     * Since each result row provides the values of the {@code PropertyState},
     * which matched the query, this iterator needs to filter the individual
     * property values.
     *
     * Additional the iterator keeps track of principal names that have already
     * been served and will not return duplicates.
     *
     * @see #findPrincipals(String, int)
     * @see #findPrincipals(int)
     */
    private final class GroupPrincipalIterator extends AbstractLazyIterator<Principal> {

        private final Set<String> processed = new HashSet<String>();

        private final String queryString;
        private final Iterator<? extends ResultRow> rows;

        private Iterator<String> propValues = Collections.emptyIterator();

        private GroupPrincipalIterator(@Nullable String queryString, @NotNull Result queryResult) {
            this.queryString = queryString;
            rows = queryResult.getRows().iterator();
        }

        @Override
        protected Principal getNext() {
            if (!propValues.hasNext()) {
                if (rows.hasNext()) {
                    propValues = rows.next().getValue(REP_EXTERNAL_PRINCIPAL_NAMES).getValue(Type.STRINGS).iterator();
                } else {
                    propValues = Collections.emptyIterator();
                }
            }
            while (propValues.hasNext()) {
                String principalName = propValues.next();
                if (principalName != null && !processed.contains(principalName) && matchesQuery(principalName) ) {
                    processed.add(principalName);
                    return new ExternalGroupPrincipal(principalName);
                }
            }
            return null;
        }

        private boolean matchesQuery(@NotNull String principalName) {
            if (queryString == null) {
                return true;
            } else {
                return principalName.contains(queryString);
            }
        }
    }

    /**
     * {@code Principal} iterator representing the members of a given
     * {@link ExternalGroupPrincipal}. The members are collected through an
     * Oak {@link org.apache.jackrabbit.oak.query.Query Query}.
     *
     * Note that the query result is subject to permission evaluation for
     * the editing {@link Root} based on the accessibility of the individual
     * {@link #REP_EXTERNAL_PRINCIPAL_NAMES} properties that contain the
     * exact name of the external group principal.
     *
     * @see ExternalGroupPrincipal#members()
     */
    private final class MemberIterator extends AbstractLazyIterator<Principal> {

        /**
         * The query results containing the path of the user accounts
         * (i.e. members) that contain the target group principal in the
         * {@link #REP_EXTERNAL_PRINCIPAL_NAMES} property values.
         */
        private final Iterator<? extends ResultRow> rows;

        private MemberIterator(@NotNull Result queryResult) {
            rows = queryResult.getRows().iterator();
        }

        @Override
        protected Principal getNext() {
            while (rows.hasNext()) {
                String userPath = rows.next().getPath();
                try {
                    Authorizable authorizable = userManager.getAuthorizableByPath(userPath);
                    if (authorizable != null) {
                        return authorizable.getPrincipal();
                    }
                } catch (RepositoryException e) {
                    log.debug("{}", e.getMessage());
                }
            }
            return null;
        }
    }

    private final class AutoMembershipPrincipals {

        private final Map<String, String[]> autoMembershipMapping;
        private final Map<String, Set<Principal>> principalMap;

        private AutoMembershipPrincipals(@NotNull Map<String, String[]> autoMembershipMapping) {
            this.autoMembershipMapping = autoMembershipMapping;
            this.principalMap = new ConcurrentHashMap<String, Set<Principal>>(autoMembershipMapping.size());
        }

        @NotNull
        private Collection<Principal> get(@Nullable String idpName) {
            if (idpName == null) {
                return ImmutableSet.of();
            }

            Set<Principal> principals;
            if (!principalMap.containsKey(idpName)) {
                String[] vs = autoMembershipMapping.get(idpName);
                if (vs == null) {
                    principals = ImmutableSet.of();
                } else {
                    ImmutableSet.Builder<Principal> builder = ImmutableSet.builder();
                    for (String groupId : autoMembershipMapping.get(idpName)) {
                        try {
                            Authorizable gr = userManager.getAuthorizable(groupId);
                            if (gr != null && gr.isGroup()) {
                                Principal grPrincipal = gr.getPrincipal();
                                if (GroupPrincipals.isGroup(grPrincipal)) {
                                    builder.add(grPrincipal);
                                } else {
                                    log.warn("Principal of group {} is not of group type -> Ignoring", groupId);
                                }
                            } else {
                                log.warn("Configured auto-membership group {} does not exist -> Ignoring", groupId);
                            }
                        } catch (RepositoryException e) {
                            log.debug("Failed to retrieved 'auto-membership' group with id {}", groupId, e);
                        }
                    }
                    principals = builder.build();
                }
                principalMap.put(idpName, principals);
            } else {
                principals = principalMap.get(idpName);
            }
            return principals;
        }
    }
}
