/*
 * 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.sling.jcr.jackrabbit.accessmanager.post;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;

import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import javax.jcr.RepositoryException;
import javax.jcr.Session;
import javax.jcr.Value;
import javax.jcr.ValueFactory;
import javax.jcr.security.AccessControlManager;
import javax.jcr.security.Privilege;

import org.apache.jackrabbit.oak.security.authorization.restriction.RestrictionProviderImpl;
import org.apache.jackrabbit.oak.spi.security.authorization.accesscontrol.AccessControlConstants;
import org.apache.jackrabbit.oak.spi.security.authorization.restriction.RestrictionDefinition;
import org.apache.jackrabbit.oak.spi.security.authorization.restriction.RestrictionProvider;
import org.apache.jackrabbit.oak.spi.security.privilege.PrivilegeConstants;
import org.apache.jackrabbit.value.ValueFactoryImpl;
import org.apache.sling.jcr.base.util.AccessControlUtil;
import org.apache.sling.jcr.jackrabbit.accessmanager.LocalPrivilege;
import org.apache.sling.jcr.jackrabbit.accessmanager.LocalRestriction;
import org.apache.sling.testing.mock.sling.ResourceResolverType;
import org.apache.sling.testing.mock.sling.junit.SlingContext;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;

/**
 * Tests for {@link LocalPrivilege}
 */
public class LocalPrivilegeTest {

    @Rule
    public final SlingContext context = new SlingContext(ResourceResolverType.JCR_OAK);

    private AccessControlManager acm;
    private Map<String, RestrictionDefinition> srMap;

    @Before
    public void setup() throws RepositoryException {
        Session session = context.resourceResolver().adaptTo(Session.class);
        acm = AccessControlUtil.getAccessControlManager(session);
        context.registerService(new RestrictionProviderImpl());
    }

    private Privilege priv(String privilegeName) throws RepositoryException {
        return acm.privilegeFromName(privilegeName);
    }

    private RestrictionDefinition rd(String restrictionName) throws Exception {
        if (srMap == null) {
            //make a temp map for quick lookup below
            RestrictionProvider restrictionProvider = context.getService(RestrictionProvider.class);
            Set<RestrictionDefinition> supportedRestrictions = restrictionProvider.getSupportedRestrictions("/");
            srMap = new HashMap<>();
            for (RestrictionDefinition restrictionDefinition : supportedRestrictions) {
                srMap.put(restrictionDefinition.getName(), restrictionDefinition);
            }
        }
        return srMap.get(restrictionName);
    }

    private Value val(String value) {
        return ValueFactoryImpl.getInstance().createValue(value);
    }
    private Value[] vals(String ... value) {
        Value[] values = new Value[value.length];
        ValueFactory vf = ValueFactoryImpl.getInstance();
        for (int i = 0; i < value.length; i++) {
            values[i] = vf.createValue(value[i]);
        }
        return values;
    }

    /**
     * Test method for {@link org.apache.sling.jcr.jackrabbit.accessmanager.LocalPrivilege#hashCode()}.
     */
    @Test
    public void testHashCode() throws RepositoryException {
        LocalPrivilege lp1 = new LocalPrivilege(priv(PrivilegeConstants.JCR_READ));
        LocalPrivilege lp2 = new LocalPrivilege(priv(PrivilegeConstants.JCR_WRITE));
        assertNotEquals(lp1.hashCode(), lp2.hashCode());

        LocalPrivilege lp3 = new LocalPrivilege(priv(PrivilegeConstants.JCR_READ));
        assertEquals(lp1.hashCode(), lp3.hashCode());

        LocalPrivilege lp4 = new LocalPrivilege(priv(PrivilegeConstants.JCR_READ));
        lp4.setAllow(true);
        assertNotEquals(lp1.hashCode(), lp4.hashCode());
        lp4.setDeny(true);
        assertNotEquals(lp1.hashCode(), lp4.hashCode());
        lp4.setAllowRestrictions(null);
        assertNotEquals(lp1.hashCode(), lp4.hashCode());
        lp4.setDenyRestrictions(null);
        assertNotEquals(lp1.hashCode(), lp4.hashCode());

        LocalPrivilege lp5 = new LocalPrivilege(null);
        assertNotEquals(lp1.hashCode(), lp5.hashCode());
    }

    /**
     * Test method for {@link org.apache.sling.jcr.jackrabbit.accessmanager.LocalPrivilege#getPrivilege()}.
     */
    @Test
    public void testGetPrivilege() throws RepositoryException {
        LocalPrivilege lp1 = new LocalPrivilege(priv(PrivilegeConstants.JCR_READ));
        assertEquals(priv(PrivilegeConstants.JCR_READ), lp1.getPrivilege());
    }

    /**
     * Test method for {@link org.apache.sling.jcr.jackrabbit.accessmanager.LocalPrivilege#getName()}.
     */
    @Test
    public void testGetName() throws RepositoryException {
        LocalPrivilege lp1 = new LocalPrivilege(priv(PrivilegeConstants.JCR_READ));
        assertEquals(PrivilegeConstants.JCR_READ, lp1.getName());
    }

    /**
     * Test method for {@link org.apache.sling.jcr.jackrabbit.accessmanager.LocalPrivilege#isNone()}.
     */
    @Test
    public void testIsNone() throws RepositoryException {
        LocalPrivilege lp1 = new LocalPrivilege(priv(PrivilegeConstants.JCR_READ));
        assertTrue(lp1.isNone());

        // deny set, allow not set
        lp1.setDeny(true);
        assertFalse(lp1.isNone());

        // allow set, deny set
        lp1.setAllow(true);
        assertFalse(lp1.isNone());

        // deny not set, allow set
        lp1.setDeny(false);
        assertFalse(lp1.isNone());
    }

    /**
     * Test method for {@link org.apache.sling.jcr.jackrabbit.accessmanager.LocalPrivilege#isAllow()}.
     */
    @Test
    public void testIsAllow() throws RepositoryException {
        LocalPrivilege lp1 = new LocalPrivilege(priv(PrivilegeConstants.JCR_READ));
        assertFalse(lp1.isAllow());

        lp1.setAllow(true);
        assertTrue(lp1.isAllow());
    }

    /**
     * Test method for {@link org.apache.sling.jcr.jackrabbit.accessmanager.LocalPrivilege#isDeny()}.
     */
    @Test
    public void testIsDeny() throws RepositoryException {
        LocalPrivilege lp1 = new LocalPrivilege(priv(PrivilegeConstants.JCR_READ));
        assertFalse(lp1.isDeny());

        lp1.setDeny(true);
        assertTrue(lp1.isDeny());
    }

    /**
     * Test method for {@link org.apache.sling.jcr.jackrabbit.accessmanager.LocalPrivilege#getAllowRestrictions()}.
     */
    @Test
    public void testGetAllowRestrictions() throws Exception {
        LocalPrivilege lp1 = new LocalPrivilege(priv(PrivilegeConstants.JCR_READ));
        Set<LocalRestriction> allowRestrictions = lp1.getAllowRestrictions();
        assertNotNull(allowRestrictions);
        assertTrue(allowRestrictions.isEmpty());

        Set<LocalRestriction> newAllowRestrictions = new HashSet<>();
        newAllowRestrictions.add(new LocalRestriction(rd(AccessControlConstants.REP_GLOB), val("/hello")));
        lp1.setAllowRestrictions(newAllowRestrictions);
        Set<LocalRestriction> allowRestrictions2 = lp1.getAllowRestrictions();
        assertNotNull(allowRestrictions2);
        assertFalse(allowRestrictions2.isEmpty());
        assertEquals(newAllowRestrictions, allowRestrictions2);
    }

    /**
     * Test method for {@link org.apache.sling.jcr.jackrabbit.accessmanager.LocalPrivilege#getDenyRestrictions()}.
     */
    @Test
    public void testGetDenyRestrictions() throws Exception {
        LocalPrivilege lp1 = new LocalPrivilege(priv(PrivilegeConstants.JCR_READ));
        Set<LocalRestriction> denyRestrictions = lp1.getDenyRestrictions();
        assertNotNull(denyRestrictions);
        assertTrue(denyRestrictions.isEmpty());

        Set<LocalRestriction> newDenyRestrictions = new HashSet<>();
        newDenyRestrictions.add(new LocalRestriction(rd(AccessControlConstants.REP_GLOB), val("/hello")));
        lp1.setDenyRestrictions(newDenyRestrictions);
        Set<LocalRestriction> denyRestrictions2 = lp1.getDenyRestrictions();
        assertNotNull(denyRestrictions2);
        assertFalse(denyRestrictions2.isEmpty());
        assertEquals(newDenyRestrictions, denyRestrictions2);
    }

    /**
     * Test method for {@link org.apache.sling.jcr.jackrabbit.accessmanager.LocalPrivilege#sameAllowRestrictions(org.apache.sling.jcr.jackrabbit.accessmanager.LocalPrivilege)}.
     */
    @Test
    public void testSameAllowRestrictions() throws Exception {
        LocalPrivilege lp1 = new LocalPrivilege(priv(PrivilegeConstants.JCR_READ));
        LocalPrivilege lp2 = new LocalPrivilege(priv(PrivilegeConstants.JCR_WRITE));
        assertTrue(lp1.sameAllowRestrictions(lp2.getAllowRestrictions()));

        Set<LocalRestriction> newAllowRestrictions1 = new HashSet<>();
        newAllowRestrictions1.add(new LocalRestriction(rd(AccessControlConstants.REP_GLOB), val("/hello")));
        newAllowRestrictions1.add(new LocalRestriction(rd(AccessControlConstants.REP_ITEM_NAMES), vals("item1", "item2")));
        lp1.setAllowRestrictions(newAllowRestrictions1);
        assertFalse(lp1.sameAllowRestrictions(lp2.getAllowRestrictions()));

        Set<LocalRestriction> newAllowRestrictions2 = new HashSet<>();
        newAllowRestrictions2.add(new LocalRestriction(rd(AccessControlConstants.REP_GLOB), val("/hello")));
        newAllowRestrictions2.add(new LocalRestriction(rd(AccessControlConstants.REP_ITEM_NAMES), vals("item1", "item2")));
        lp2.setAllowRestrictions(newAllowRestrictions2);
        assertTrue(lp1.sameAllowRestrictions(lp2.getAllowRestrictions()));

        Set<LocalRestriction> newAllowRestrictions3 = new HashSet<>();
        newAllowRestrictions3.add(new LocalRestriction(rd(AccessControlConstants.REP_GLOB), val("/hello")));
        newAllowRestrictions3.add(new LocalRestriction(rd(AccessControlConstants.REP_ITEM_NAMES), vals("item1", "item2_changed")));
        lp2.setAllowRestrictions(newAllowRestrictions3);
        assertFalse(lp1.sameAllowRestrictions(lp2.getAllowRestrictions()));
    }

    /**
     * Test method for {@link org.apache.sling.jcr.jackrabbit.accessmanager.LocalPrivilege#sameDenyRestrictions(org.apache.sling.jcr.jackrabbit.accessmanager.LocalPrivilege)}.
     */
    @Test
    public void testSameDenyRestrictions() throws Exception {
        LocalPrivilege lp1 = new LocalPrivilege(priv(PrivilegeConstants.JCR_READ));
        LocalPrivilege lp2 = new LocalPrivilege(priv(PrivilegeConstants.JCR_WRITE));
        assertTrue(lp1.sameDenyRestrictions(lp2.getDenyRestrictions()));

        Set<LocalRestriction> newDenyRestrictions1 = new HashSet<>();
        newDenyRestrictions1.add(new LocalRestriction(rd(AccessControlConstants.REP_GLOB), val("/hello")));
        newDenyRestrictions1.add(new LocalRestriction(rd(AccessControlConstants.REP_ITEM_NAMES), vals("item1", "item2")));
        lp1.setDenyRestrictions(newDenyRestrictions1);
        assertFalse(lp1.sameDenyRestrictions(lp2.getDenyRestrictions()));

        Set<LocalRestriction> newDenyRestrictions2 = new HashSet<>();
        newDenyRestrictions2.add(new LocalRestriction(rd(AccessControlConstants.REP_GLOB), val("/hello")));
        newDenyRestrictions2.add(new LocalRestriction(rd(AccessControlConstants.REP_ITEM_NAMES), vals("item1", "item2")));
        lp2.setDenyRestrictions(newDenyRestrictions2);
        assertTrue(lp1.sameDenyRestrictions(lp2.getDenyRestrictions()));

        Set<LocalRestriction> newDenyRestrictions3 = new HashSet<>();
        newDenyRestrictions3.add(new LocalRestriction(rd(AccessControlConstants.REP_GLOB), val("/hello")));
        newDenyRestrictions3.add(new LocalRestriction(rd(AccessControlConstants.REP_ITEM_NAMES), vals("item1", "item2_changed")));
        lp2.setDenyRestrictions(newDenyRestrictions3);
        assertFalse(lp1.sameDenyRestrictions(lp2.getDenyRestrictions()));
    }

    /**
     * Test method for {@link org.apache.sling.jcr.jackrabbit.accessmanager.LocalPrivilege#sameAllowAndDenyRestrictions()}.
     */
    @Test
    public void testSameAllowAndDenyRestrictions() throws Exception {
        LocalPrivilege lp1 = new LocalPrivilege(priv(PrivilegeConstants.JCR_READ));
        assertTrue(lp1.sameAllowAndDenyRestrictions());

        Set<LocalRestriction> newDenyRestrictions1 = new HashSet<>();
        newDenyRestrictions1.add(new LocalRestriction(rd(AccessControlConstants.REP_GLOB), val("/hello")));
        newDenyRestrictions1.add(new LocalRestriction(rd(AccessControlConstants.REP_ITEM_NAMES), vals("item1", "item2")));
        lp1.setDenyRestrictions(newDenyRestrictions1);
        assertFalse(lp1.sameAllowAndDenyRestrictions());

        Set<LocalRestriction> newAllowRestrictions1 = new HashSet<>();
        newAllowRestrictions1.add(new LocalRestriction(rd(AccessControlConstants.REP_GLOB), val("/hello")));
        newAllowRestrictions1.add(new LocalRestriction(rd(AccessControlConstants.REP_ITEM_NAMES), vals("item1", "item2")));
        lp1.setAllowRestrictions(newAllowRestrictions1);
        assertTrue(lp1.sameAllowAndDenyRestrictions());

        Set<LocalRestriction> newAllowRestrictions2 = new HashSet<>();
        newAllowRestrictions2.add(new LocalRestriction(rd(AccessControlConstants.REP_GLOB), val("/hello")));
        newAllowRestrictions2.add(new LocalRestriction(rd(AccessControlConstants.REP_ITEM_NAMES), vals("item1", "item2_changed")));
        lp1.setAllowRestrictions(newAllowRestrictions2);
        assertFalse(lp1.sameAllowAndDenyRestrictions());
    }

    /**
     * Test method for {@link org.apache.sling.jcr.jackrabbit.accessmanager.LocalPrivilege#toString()}.
     */
    @Test
    public void testToString() throws RepositoryException {
        LocalPrivilege lp1 = new LocalPrivilege(priv(PrivilegeConstants.JCR_READ));
        assertNotNull(lp1.toString());
    }

    /**
     * Test method for {@link org.apache.sling.jcr.jackrabbit.accessmanager.LocalPrivilege#equals(java.lang.Object)}.
     */
    @Test
    public void testEqualsObject() throws Exception {
        LocalPrivilege lp1 = new LocalPrivilege(priv(PrivilegeConstants.JCR_READ));
        assertEquals(lp1, lp1);
        assertNotEquals(lp1, null);
        assertNotEquals(lp1, this);

        LocalPrivilege lp2 = new LocalPrivilege(priv(PrivilegeConstants.JCR_WRITE));
        assertNotEquals(lp1, lp2);

        LocalPrivilege lp3 = new LocalPrivilege(priv(PrivilegeConstants.JCR_READ));
        assertEquals(lp1, lp3);

        LocalPrivilege lp4 = new LocalPrivilege(priv(PrivilegeConstants.JCR_READ));
        lp4.setAllow(true);
        assertNotEquals(lp1, lp4);

        LocalPrivilege lp5 = new LocalPrivilege(priv(PrivilegeConstants.JCR_READ));
        lp5.setDeny(true);
        assertNotEquals(lp1, lp5);

        LocalPrivilege lp6 = new LocalPrivilege(priv(PrivilegeConstants.JCR_READ));
        lp6.setAllowRestrictions(null);
        assertNotEquals(lp1, lp6);

        LocalPrivilege lp7 = new LocalPrivilege(priv(PrivilegeConstants.JCR_READ));
        lp7.setDenyRestrictions(null);
        assertNotEquals(lp1, lp7);

        LocalPrivilege lp8 = new LocalPrivilege(priv(PrivilegeConstants.JCR_READ));
        lp8.setAllowRestrictions(null);
        LocalPrivilege lp9 = new LocalPrivilege(priv(PrivilegeConstants.JCR_READ));
        assertNotEquals(lp8, lp9);

        LocalPrivilege lp10 = new LocalPrivilege(priv(PrivilegeConstants.JCR_READ));
        lp10.setDenyRestrictions(null);
        LocalPrivilege lp11 = new LocalPrivilege(priv(PrivilegeConstants.JCR_READ));
        assertNotEquals(lp10, lp11);

        LocalPrivilege lp12 = new LocalPrivilege(priv(PrivilegeConstants.JCR_READ));
        lp12.setAllowRestrictions(new HashSet<>(Arrays.asList(new LocalRestriction(rd(AccessControlConstants.REP_GLOB), val("/hello")))));
        LocalPrivilege lp13 = new LocalPrivilege(priv(PrivilegeConstants.JCR_READ));
        assertNotEquals(lp12, lp13);

        LocalPrivilege lp14 = new LocalPrivilege(priv(PrivilegeConstants.JCR_READ));
        lp14.setDenyRestrictions(new HashSet<>(Arrays.asList(new LocalRestriction(rd(AccessControlConstants.REP_GLOB), val("/hello")))));
        LocalPrivilege lp15 = new LocalPrivilege(priv(PrivilegeConstants.JCR_READ));
        assertNotEquals(lp14, lp15);

        LocalPrivilege lp16 = new LocalPrivilege(null);
        LocalPrivilege lp17 = new LocalPrivilege(priv(PrivilegeConstants.JCR_READ));
        assertNotEquals(lp16, lp17);

        LocalPrivilege lp18 = new LocalPrivilege(priv(PrivilegeConstants.JCR_READ));
        LocalPrivilege lp19 = new LocalPrivilege(null);
        assertNotEquals(lp18, lp19);

        LocalPrivilege lp20 = new LocalPrivilege(null);
        LocalPrivilege lp21 = new LocalPrivilege(null);
        assertEquals(lp20, lp21);

        LocalPrivilege lp22 = new LocalPrivilege(priv(PrivilegeConstants.JCR_READ));
        lp22.setAllowRestrictions(null);
        LocalPrivilege lp23 = new LocalPrivilege(priv(PrivilegeConstants.JCR_READ));
        lp23.setAllowRestrictions(null);
        assertEquals(lp22, lp23);

        LocalPrivilege lp24 = new LocalPrivilege(priv(PrivilegeConstants.JCR_READ));
        lp24.setDenyRestrictions(null);
        LocalPrivilege lp25 = new LocalPrivilege(priv(PrivilegeConstants.JCR_READ));
        lp25.setDenyRestrictions(null);
        assertEquals(lp24, lp25);
    }

}
