/*
 * 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.nifi.registry.ranger;

import org.apache.commons.lang3.StringUtils;
import org.apache.nifi.registry.security.authorization.AccessPolicy;
import org.apache.nifi.registry.security.authorization.Group;
import org.apache.nifi.registry.security.authorization.RequestAction;
import org.apache.nifi.registry.security.authorization.User;
import org.apache.nifi.registry.security.authorization.UserGroupProvider;
import org.apache.nifi.registry.security.authorization.exception.AuthorizationAccessException;
import org.apache.ranger.plugin.service.RangerBasePlugin;
import org.apache.ranger.plugin.util.ServicePolicies;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * Extends the base plugin to convert service policies into NiFi Registry policy domain model.
 */
public class RangerBasePluginWithPolicies extends RangerBasePlugin {

    private static final Logger logger = LoggerFactory.getLogger(RangerBasePluginWithPolicies.class);

    private final static String WILDCARD_ASTERISK = "*";

    private UserGroupProvider userGroupProvider;
    private AtomicReference<PolicyLookup> policies = new AtomicReference<>(new PolicyLookup());

    public RangerBasePluginWithPolicies(final String serviceType, final String appId) {
        this(serviceType, appId, null);
    }

    public RangerBasePluginWithPolicies(final String serviceType, final String appId, final UserGroupProvider userGroupProvider) {
        super(serviceType, appId);
        this.userGroupProvider = userGroupProvider; // will be null if used outside of the managed RangerAuthorizer
    }

    @Override
    public void setPolicies(final ServicePolicies policies) {
        super.setPolicies(policies);

        if (policies == null || policies.getPolicies() == null) {
            this.policies.set(new PolicyLookup());
        } else {
            this.policies.set(createPolicyLookup(policies));
        }
    }

    /**
     * Determines if a policy exists for the given resource.
     *
     * @param resourceIdentifier the id of the resource
     *
     * @return true if a policy exists for the given resource, false otherwise
     */
    public boolean doesPolicyExist(final String resourceIdentifier, final RequestAction requestAction) {
        if (resourceIdentifier == null) {
            return false;
        }

        final PolicyLookup policyLookup = policies.get();
        return policyLookup.getAccessPolicy(resourceIdentifier, requestAction) != null;
    }

    public Set<AccessPolicy> getAccessPolicies() throws AuthorizationAccessException {
        return policies.get().getAccessPolicies();
    }

    public AccessPolicy getAccessPolicy(String identifier) throws AuthorizationAccessException {
        return policies.get().getAccessPolicy(identifier);
    }

    public AccessPolicy getAccessPolicy(String resourceIdentifier, RequestAction action) throws AuthorizationAccessException {
        return policies.get().getAccessPolicy(resourceIdentifier, action);
    }

    private PolicyLookup createPolicyLookup(final ServicePolicies servicePolicies) {
        final Map<String, AccessPolicy> policiesByIdentifier = new HashMap<>();
        final Map<String, Map<RequestAction, AccessPolicy>> policiesByResource = new HashMap<>();

        logger.debug("Converting Ranger ServicePolicies model into NiFi Registry policy model for viewing purposes in NiFi Registry UI.");

        servicePolicies.getPolicies().stream().forEach(policy -> {
            // only consider policies that are enabled
            if (Boolean.TRUE.equals(policy.getIsEnabled())) {
                // get all the resources for this policy - excludes/recursive support disabled
                final Set<String> resources = policy.getResources().values().stream()
                        .filter(resource -> {
                            final boolean isMissingResource;
                            final boolean isWildcard;
                            if (resource.getValues() == null) {
                                isMissingResource = true;
                                isWildcard = false;
                            } else {
                                isMissingResource = false;
                                isWildcard = resource.getValues().stream().anyMatch(value -> value.contains(WILDCARD_ASTERISK));
                            }

                            final boolean isExclude = Boolean.TRUE.equals(resource.getIsExcludes());
                            final boolean isRecursive =  Boolean.TRUE.equals(resource.getIsRecursive());

                            if (isMissingResource) {
                                logger.warn("Encountered resources missing values. Skipping policy for viewing purposes. Will still be used for access decisions.");
                            }
                            if (isWildcard) {
                                logger.warn(String.format("Resources [%s] include a wildcard value. Skipping policy for viewing purposes. "
                                        + "Will still be used for access decisions.", StringUtils.join(resource.getValues(), ", ")));
                            }
                            if (isExclude) {
                                logger.warn(String.format("Resources [%s] marked as an exclude policy. Skipping policy for viewing purposes. "
                                        + "Will still be used for access decisions.", StringUtils.join(resource.getValues(), ", ")));
                            }
                            if (isRecursive) {
                                logger.warn(String.format("Resources [%s] marked as a recursive policy. Skipping policy for viewing purposes. "
                                        + "Will still be used for access decisions.", StringUtils.join(resource.getValues(), ", ")));
                            }

                            return !isMissingResource && !isWildcard && !isExclude && !isRecursive;
                        })
                        .flatMap(resource -> resource.getValues().stream())
                        .collect(Collectors.toSet());

                policy.getPolicyItems().forEach(policyItem -> {
                    // get all the users for this policy item, excluding unknown users
                    final Set<String> userIds = policyItem.getUsers().stream()
                            .map(userIdentity -> getUser(userIdentity))
                            .filter(Objects::nonNull)
                            .map(user -> user.getIdentifier())
                            .collect(Collectors.toSet());

                    // get all groups for this policy item, excluding unknown groups
                    final Set<String> groupIds = policyItem.getGroups().stream()
                            .map(groupName -> getGroup(groupName))
                            .filter(Objects::nonNull)
                            .map(group -> group.getIdentifier())
                            .collect(Collectors.toSet());

                    // check if this policy item is a delegate admin
                    final boolean isDelegateAdmin = Boolean.TRUE.equals(policyItem.getDelegateAdmin());

                    policyItem.getAccesses().forEach(access -> {
                        try {
                            // interpret the request action
                            final RequestAction action = RequestAction.valueOf(access.getType());

                            // function for creating an access policy
                            final Function<String, AccessPolicy> createPolicy = resource -> new AccessPolicy.Builder()
                                    .identifierGenerateFromSeed(resource + access.getType())
                                    .resource(resource)
                                    .action(action)
                                    .addUsers(userIds)
                                    .addGroups(groupIds)
                                    .build();

                            resources.forEach(resource -> {
                                // create the access policy for the specified resource
                                final AccessPolicy accessPolicy = createPolicy.apply(resource);
                                policiesByIdentifier.put(accessPolicy.getIdentifier(), accessPolicy);
                                policiesByResource.computeIfAbsent(resource, r -> new HashMap<>()).put(action, accessPolicy);

                                // if this is a delegate admin, also create the admin policy for the specified resource
                                if (isDelegateAdmin) {
                                    //  build the admin resource identifier
                                    final String adminResource;
                                    if (resource.startsWith("/")) {
                                        adminResource = "/policies" + resource;
                                    } else {
                                        adminResource = "/policies/" + resource;
                                    }

                                    final AccessPolicy adminAccessPolicy = createPolicy.apply(adminResource);
                                    policiesByIdentifier.put(adminAccessPolicy.getIdentifier(), adminAccessPolicy);
                                    policiesByResource.computeIfAbsent(adminResource, ar -> new HashMap<>()).put(action, adminAccessPolicy);
                                }
                            });
                        } catch (final IllegalArgumentException e) {
                            logger.warn(String.format("Unrecognized request action '%s'. Skipping policy for viewing purposes. Will still be used for access decisions.", access.getType()));
                        }
                    });
                });
            }
        });

        return new PolicyLookup(policiesByIdentifier, policiesByResource);
    }

    private User getUser(final String identity) {
        if (userGroupProvider == null) {
            // generate the user deterministically when running outside of the ManagedRangerAuthorizer
            return new User.Builder().identifierGenerateFromSeed(identity).identity(identity).build();
        } else {
            // find the user in question
            final User user = userGroupProvider.getUserByIdentity(identity);

            if (user == null) {
                logger.warn(String.format("Cannot find user '%s' in the configured User Group Provider. Skipping user for viewing purposes. Will still be used for access decisions.", identity));
            }

            return user;
        }
    }

    private Group getGroup(final String name) {
        if (userGroupProvider == null) {
            // generate the group deterministically when running outside of the ManagedRangerAuthorizer
            return new Group.Builder().identifierGenerateFromSeed(name).name(name).build();
        } else {
            // find the group in question
            final Group group = userGroupProvider.getGroups().stream().filter(g -> g.getName().equals(name)).findFirst().orElse(null);

            if (group == null) {
                logger.warn(String.format("Cannot find group '%s' in the configured User Group Provider. Skipping group for viewing purposes. Will still be used for access decisions.", name));
            }

            return group;
        }
    }

    private static class PolicyLookup {

        private final Map<String, AccessPolicy> policiesByIdentifier;
        private final Map<String, Map<RequestAction, AccessPolicy>> policiesByResource;
        private final Set<AccessPolicy> allPolicies;

        private PolicyLookup() {
            this(null, null);
        }

        private PolicyLookup(final Map<String, AccessPolicy> policiesByIdentifier, final Map<String, Map<RequestAction, AccessPolicy>> policiesByResource) {
            if (policiesByIdentifier == null) {
                allPolicies = Collections.EMPTY_SET;
            } else {
                allPolicies = Collections.unmodifiableSet(new HashSet<>(policiesByIdentifier.values()));
            }

            this.policiesByIdentifier = policiesByIdentifier;
            this.policiesByResource = policiesByResource;
        }

        private Set<AccessPolicy> getAccessPolicies() throws AuthorizationAccessException {
            return allPolicies;
        }

        private AccessPolicy getAccessPolicy(String identifier) throws AuthorizationAccessException {
            if (policiesByIdentifier == null) {
                return null;
            }

            return policiesByIdentifier.get(identifier);
        }

        private AccessPolicy getAccessPolicy(String resourceIdentifier, RequestAction action) throws AuthorizationAccessException {
            if (policiesByResource == null) {
                return null;
            }

            final Map<RequestAction, AccessPolicy> policiesForResource = policiesByResource.get(resourceIdentifier);

            if (policiesForResource != null) {
                return policiesForResource.get(action);
            }

            return null;
        }
    }

}
