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

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.jcr.PropertyType;
import javax.jcr.RepositoryException;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
import org.apache.jackrabbit.api.security.JackrabbitAccessControlEntry;
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.spi.security.authorization.restriction.AbstractRestrictionProvider;
import org.apache.jackrabbit.oak.spi.security.authorization.restriction.Restriction;
import org.apache.jackrabbit.oak.spi.security.authorization.restriction.RestrictionDefinition;
import org.apache.jackrabbit.oak.spi.security.authorization.restriction.RestrictionDefinitionImpl;
import org.apache.jackrabbit.oak.spi.security.authorization.restriction.RestrictionPattern;
import org.apache.jackrabbit.oak.spi.security.authorization.restriction.RestrictionProvider;
import org.apache.jackrabbit.oak.spi.security.principal.PrincipalImpl;
import org.apache.jackrabbit.oak.spi.security.privilege.PrivilegeBits;
import org.apache.jackrabbit.oak.spi.security.privilege.PrivilegeConstants;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.junit.Test;
import org.mockito.Mockito;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.when;

/**
 * Tests for functionality provided by {@link AbstractAccessControlList}.
 */
public class AbstractAccessControlListTest extends AbstractAccessControlTest {

    protected String getTestPath() {
        return "/testPath";
    }

    protected NamePathMapper getNamePathMapper() {
        return NamePathMapper.DEFAULT;
    }

    protected RestrictionProvider getRestrictionProvider() {
        Map<String, RestrictionDefinition> rDefs = new HashMap();
        rDefs.put("r1", new RestrictionDefinitionImpl("r1", Type.STRING, true));
        rDefs.put("r2", new RestrictionDefinitionImpl("r2", Type.LONGS, false));

        return new AbstractRestrictionProvider(rDefs) {
            @NotNull
            @Override
            public RestrictionPattern getPattern(@Nullable String oakPath, @NotNull Tree tree) {
                throw new UnsupportedOperationException();
            }

            @NotNull
            @Override
            public RestrictionPattern getPattern(@Nullable String oakPath, @NotNull Set<Restriction> restrictions) {
                throw new UnsupportedOperationException();
            }
        };
    }

    protected AbstractAccessControlList createEmptyACL() {
        return createACL(getTestPath(), Collections.<JackrabbitAccessControlEntry>emptyList(), getNamePathMapper());
    }

    protected AbstractAccessControlList createACL(@NotNull JackrabbitAccessControlEntry... entries) {
        return createACL(getTestPath(), Lists.newArrayList(entries), getNamePathMapper());
    }

    protected AbstractAccessControlList createACL(@NotNull List<JackrabbitAccessControlEntry> entries) {
        return createACL(getTestPath(), entries, getNamePathMapper());
    }

    protected AbstractAccessControlList createACL(@Nullable String jcrPath,
                                                  @NotNull ACE... entries) {
        return createACL(jcrPath, Lists.newArrayList(entries), getNamePathMapper());
    }

    protected AbstractAccessControlList createACL(@Nullable String jcrPath,
                                                  @NotNull List<JackrabbitAccessControlEntry> entries,
                                                  @NotNull NamePathMapper namePathMapper) {
        return createACL(jcrPath, entries, namePathMapper, getRestrictionProvider());
    }

    protected AbstractAccessControlList createACL(@Nullable String jcrPath,
                                                  @NotNull List<JackrabbitAccessControlEntry> entries,
                                                  @NotNull NamePathMapper namePathMapper,
                                                  @NotNull RestrictionProvider restrictionProvider) {
        return new TestACL(jcrPath, restrictionProvider, namePathMapper, entries);
    }

    protected List<JackrabbitAccessControlEntry> createTestEntries() throws RepositoryException {
        List<JackrabbitAccessControlEntry> entries = new ArrayList(3);
        for (int i = 0; i < 3; i++) {
            entries.add(createEntry(
                    new PrincipalImpl("testPrincipal" + i), PrivilegeBits.BUILT_IN.get(PrivilegeConstants.JCR_READ), true));
        }
        return entries;
    }

    @Test
    public void testGetNamePathMapper() throws Exception {
        assertSame(getNamePathMapper(), createEmptyACL().getNamePathMapper());
        assertSame(NamePathMapper.DEFAULT, createACL(getTestPath(), ImmutableList.<JackrabbitAccessControlEntry>of(), NamePathMapper.DEFAULT).getNamePathMapper());
    }

    @Test
    public void testGetPath() {
        NamePathMapper npMapper = mockNamePathMapper(getTestPath());

        // map of jcr-path to standard jcr-path
        Map<String, String> paths = new HashMap<String, String>();
        paths.put(null, null);
        paths.put(getTestPath(), getTestPath());
        paths.put("/", "/");
        paths.put("/jr:testPath", "/jr:testPath");
        paths.put("/{http://jackrabbit.apache.org}testPath", "/jr:testPath");

        for (String path : paths.keySet()) {
            AbstractAccessControlList acl = createACL(path, Collections.<JackrabbitAccessControlEntry>emptyList(), npMapper);
            assertEquals(paths.get(path), acl.getPath());
        }
    }

    @Test
    public void testGetOakPath() {
        NamePathMapper npMapper = mockNamePathMapper(getTestPath());

        // map of jcr-path to oak path
        Map<String, String> paths = new HashMap<String, String>();
        paths.put(null, null);
        paths.put(getTestPath(), getTestPath());
        paths.put("/", "/");
        String oakPath = "/oak:testPath";
        paths.put("/jr:testPath", oakPath);
        paths.put("/{http://jackrabbit.apache.org}testPath", oakPath);

        // test if oak-path is properly set.
        for (String path : paths.keySet()) {
            AbstractAccessControlList acl = createACL(path, Collections.<JackrabbitAccessControlEntry>emptyList(), npMapper);
            assertEquals(paths.get(path), acl.getOakPath());
        }
    }

    private static NamePathMapper mockNamePathMapper(String testPath) {
        NamePathMapper npMapper = Mockito.mock(NamePathMapper.class);
        when(npMapper.getOakPath("/")).thenReturn("/");
        when(npMapper.getOakPath(null)).thenReturn(null);
        when(npMapper.getOakPath(testPath)).thenReturn(testPath);
        when(npMapper.getOakPath("/jr:testPath")).thenReturn("/oak:testPath");
        when(npMapper.getOakPath("/{http://jackrabbit.apache.org}testPath")).thenReturn("/oak:testPath");
        when(npMapper.getJcrPath("/")).thenReturn("/");
        when(npMapper.getJcrPath(null)).thenReturn(null);
        when(npMapper.getJcrPath(testPath)).thenReturn(testPath);
        when(npMapper.getJcrPath("/oak:testPath")).thenReturn("/jr:testPath");
        when(npMapper.getJcrPath("/{http://jackrabbit.apache.org}testPath")).thenReturn("/jr:testPath");
        return npMapper;
    }

    @Test
    public void testEmptyAcl() throws RepositoryException {
        AbstractAccessControlList acl = createEmptyACL();

        assertNotNull(acl.getAccessControlEntries());
        assertNotNull(acl.getEntries());

        assertTrue(acl.getAccessControlEntries().length == 0);
        assertEquals(acl.getAccessControlEntries().length, acl.getEntries().size());
        assertEquals(0, acl.size());
        assertTrue(acl.isEmpty());
    }

    @Test
    public void testSize() throws RepositoryException {
        AbstractAccessControlList acl = createACL(createTestEntries());
        assertEquals(3, acl.size());
    }

    @Test
    public void testIsEmpty() throws RepositoryException {
        AbstractAccessControlList acl = createACL(createTestEntries());
        assertFalse(acl.isEmpty());
    }

    @Test
    public void testGetEntries() throws RepositoryException {
        List<JackrabbitAccessControlEntry> aces = createTestEntries();
        AbstractAccessControlList acl = createACL(aces);

        assertNotNull(acl.getEntries());
        assertNotNull(acl.getAccessControlEntries());

        assertEquals(aces.size(), acl.getEntries().size());
        assertEquals(aces.size(), acl.getAccessControlEntries().length);
        assertTrue(acl.getEntries().containsAll(aces));
        assertTrue(Arrays.asList(acl.getAccessControlEntries()).containsAll(aces));
    }

    @Test
    public void testGetRestrictionNames() throws RepositoryException {
        AbstractAccessControlList acl = createEmptyACL();

        String[] restrNames = acl.getRestrictionNames();
        assertNotNull(restrNames);
        List<String> names = Lists.newArrayList(restrNames);
        for (RestrictionDefinition def : getRestrictionProvider().getSupportedRestrictions(getTestPath())) {
            assertTrue(names.remove(getNamePathMapper().getJcrName(def.getName())));
        }
        assertTrue(names.isEmpty());
    }

    @Test
    public void testGetRestrictionType() throws RepositoryException {
        AbstractAccessControlList acl = createEmptyACL();
        for (RestrictionDefinition def : getRestrictionProvider().getSupportedRestrictions(getTestPath())) {
            int reqType = acl.getRestrictionType(getNamePathMapper().getJcrName(def.getName()));

            assertTrue(reqType > PropertyType.UNDEFINED);
            assertEquals(def.getRequiredType().tag(), reqType);
        }
    }

    @Test
    public void testGetRestrictionTypeForUnknownName() throws RepositoryException {
        AbstractAccessControlList acl = createEmptyACL();
        // for backwards compatibility getRestrictionType(String) must return
        // UNDEFINED for a unknown restriction name:
        assertEquals(PropertyType.UNDEFINED, acl.getRestrictionType("unknownRestrictionName"));
    }

    @Test
    public void testIsMultiValueRestriction() throws RepositoryException {
        AbstractAccessControlList acl = createEmptyACL();
        for (RestrictionDefinition def : getRestrictionProvider().getSupportedRestrictions(getTestPath())) {
            boolean isMv = acl.isMultiValueRestriction(getNamePathMapper().getJcrName(def.getName()));

            assertEquals(def.getRequiredType().isArray(), isMv);
        }
    }

    @Test
    public void testIsMultiValueRestrictionForUnknownName() throws RepositoryException {
        assertFalse(createEmptyACL().isMultiValueRestriction("unknownRestrictionName"));
    }
}
