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

import java.security.Principal;
import java.util.Collection;
import java.util.List;
import java.util.Set;
import org.apache.jackrabbit.oak.api.Root;
import org.apache.jackrabbit.oak.commons.LongUtils;
import org.apache.jackrabbit.oak.security.authorization.ProviderCtx;
import org.apache.jackrabbit.oak.spi.mount.Mount;
import org.apache.jackrabbit.oak.spi.mount.MountInfoProvider;
import org.apache.jackrabbit.oak.spi.security.ConfigurationParameters;
import org.apache.jackrabbit.oak.spi.security.Context;
import org.apache.jackrabbit.oak.spi.security.authorization.restriction.RestrictionProvider;
import org.jetbrains.annotations.NotNull;

import static com.google.common.collect.Lists.newArrayList;

public class MountPermissionProvider extends PermissionProviderImpl {

    @NotNull
    public static String getPermissionRootName(@NotNull Mount mount, @NotNull String workspace) {
        if (mount.isDefault()) {
            return workspace;
        } else {
            return mount.getPathFragmentName() + "-" + workspace;
        }
    }

    private final MountInfoProvider mountInfoProvider;

    public MountPermissionProvider(@NotNull Root root, @NotNull String workspaceName,
                                   @NotNull Set<Principal> principals, @NotNull RestrictionProvider restrictionProvider,
                                   @NotNull ConfigurationParameters options, @NotNull Context ctx,
                                   @NotNull ProviderCtx providerCtx) {
        super(root, workspaceName, principals, restrictionProvider, options, ctx, providerCtx);
        this.mountInfoProvider = providerCtx.getMountInfoProvider();
    }

    @Override
    protected PermissionStore getPermissionStore(Root root, String workspaceName,
            RestrictionProvider restrictionProvider) {
        List<PermissionStoreImpl> stores = newArrayList();
        stores.add(new PermissionStoreImpl(root, workspaceName, restrictionProvider));
        for (Mount m : mountInfoProvider.getNonDefaultMounts()) {
            String psRoot = getPermissionRootName(m, workspaceName);
            PermissionStoreImpl ps = new PermissionStoreImpl(root, psRoot, restrictionProvider);
            stores.add(ps);
        }
        return new MountPermissionStore(stores);
    }

    private static class MountPermissionStore implements PermissionStore {

        private final List<PermissionStoreImpl> stores;

        public MountPermissionStore(List<PermissionStoreImpl> stores) {
            this.stores = stores;
        }

        @NotNull
        @Override
        public Collection<PermissionEntry> load(@NotNull String principalName,
                                                @NotNull String path) {
            for (PermissionStoreImpl store : stores) {
                Collection<PermissionEntry> col = store.load(principalName, path);
                if (col != null && !col.isEmpty()) {
                    return col;
                }
            }
            return null;
        }

        @NotNull
        @Override
        public PrincipalPermissionEntries load(@NotNull String principalName) {
            PrincipalPermissionEntries ppe = new PrincipalPermissionEntries();
            for (PermissionStoreImpl store : stores) {
                ppe.putAllEntries(store.load(principalName).getEntries());
            }
            ppe.setFullyLoaded(true);
            return ppe;
        }

        @NotNull
        @Override
        public NumEntries getNumEntries(@NotNull String principalName, long max) {
            long num = 0;
            boolean isExact = true;
            for (PermissionStoreImpl store : stores) {
                NumEntries ne = store.getNumEntries(principalName, max);
                num = LongUtils.safeAdd(num, ne.size);
                if (!ne.isExact) {
                    isExact = false;
                }
                // if any of the stores doesn't reveal the exact number and max
                // is reached, stop asking the remaining stores.
                // as long as every store is reporting the exact number continue
                // in order to (possibly) be able to return the exact number.
                if (num >= max && !isExact) {
                    break;
                }
            }
            return NumEntries.valueOf(num, isExact);
        }

        @Override
        public void flush(@NotNull Root root) {
            for (PermissionStoreImpl store : stores) {
                store.flush(root);
            }
        }
    }
}
