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

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

import java.math.BigDecimal;
import java.math.BigInteger;
import java.security.Principal;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.function.Function;

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 javax.json.Json;
import javax.json.JsonArray;
import javax.json.JsonArrayBuilder;
import javax.json.JsonObject;
import javax.json.JsonObjectBuilder;
import javax.json.JsonString;
import javax.json.JsonValue;

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.CompositeRestrictionProvider;
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.principal.PrincipalImpl;
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.jetbrains.annotations.NotNull;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;

/**
 *
 */
public class JsonConvertTest {

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

    private AccessControlManager acm;

    private Map<String, RestrictionDefinition> srMap;

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

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

    private RestrictionDefinition rd(String restrictionName) {
        if (srMap == null) {
            //make a temp map for quick lookup below
            @NotNull
            RestrictionProvider[] services = context.getServices(RestrictionProvider.class, null);
            RestrictionProvider restrictionProvider = CompositeRestrictionProvider.newInstance(services);
            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.impl.JsonConvert#convertToJson(java.security.Principal, java.util.Map, int)}.
     */
    @Test
    public void testConvertToJson() throws RepositoryException {
        Principal principal = new PrincipalImpl("testuser");
        LocalPrivilege lp1 = new LocalPrivilege(priv(PrivilegeConstants.JCR_READ));
        lp1.setAllow(true);
        LocalPrivilege lp2 = new LocalPrivilege(priv(PrivilegeConstants.JCR_WRITE));
        lp2.setDeny(true);
        LocalPrivilege lp3 = new LocalPrivilege(priv(PrivilegeConstants.JCR_READ_ACCESS_CONTROL));
        LocalPrivilege lp4 = new LocalPrivilege(priv(PrivilegeConstants.JCR_NODE_TYPE_MANAGEMENT));
        lp4.setAllow(true);
        lp4.setAllowRestrictions(Collections.singleton(new LocalRestriction(rd(AccessControlConstants.REP_GLOB), val("/hello"))));
        LocalPrivilege lp5 = new LocalPrivilege(priv(PrivilegeConstants.JCR_MODIFY_ACCESS_CONTROL));
        lp5.setDeny(true);
        lp5.setDenyRestrictions(Collections.singleton(new LocalRestriction(rd(AccessControlConstants.REP_ITEM_NAMES), vals("item1", "item2"))));
        Map<Privilege, LocalPrivilege> entry = new HashMap<>();
        entry.put(lp1.getPrivilege(), lp1);
        entry.put(lp2.getPrivilege(), lp2);
        entry.put(lp3.getPrivilege(), lp3);
        entry.put(lp4.getPrivilege(), lp4);
        entry.put(lp5.getPrivilege(), lp5);
        int order = 1;
        JsonObjectBuilder principalObj = JsonConvert.convertToJson(principal, entry, order);
        assertNotNull(principalObj);
        JsonObject build = principalObj.build();
        assertEquals("testuser", build.getString(JsonConvert.KEY_PRINCIPAL));
        assertEquals(1, build.getInt(JsonConvert.KEY_ORDER));
        JsonObject privilegesObj = build.getJsonObject(JsonConvert.KEY_PRIVILEGES);
        assertNotNull(privilegesObj);
        assertEquals(4, privilegesObj.size());

        JsonValue jsonValue1 = privilegesObj.get(PrivilegeConstants.JCR_READ);
        assertTrue(jsonValue1 instanceof JsonObject);
        assertTrue(((JsonObject)jsonValue1).getBoolean(JsonConvert.KEY_ALLOW));

        JsonValue jsonValue2 = privilegesObj.get(PrivilegeConstants.JCR_WRITE);
        assertTrue(jsonValue2 instanceof JsonObject);
        assertTrue(((JsonObject)jsonValue2).getBoolean(JsonConvert.KEY_DENY));

        JsonValue jsonValue4 = privilegesObj.get(PrivilegeConstants.JCR_NODE_TYPE_MANAGEMENT);
        assertTrue(jsonValue4 instanceof JsonObject);
        JsonObject allowObj4 = ((JsonObject)jsonValue4).getJsonObject(JsonConvert.KEY_ALLOW);
        assertNotNull(allowObj4);
        Object globRestrictionObj4 = allowObj4.get(AccessControlConstants.REP_GLOB);
        assertTrue(globRestrictionObj4 instanceof JsonString);
        assertEquals("/hello", ((JsonString)globRestrictionObj4).getString());

        JsonValue jsonValue5 = privilegesObj.get(PrivilegeConstants.JCR_MODIFY_ACCESS_CONTROL);
        assertTrue(jsonValue5 instanceof JsonObject);
        JsonObject allowObj5 = ((JsonObject)jsonValue5).getJsonObject(JsonConvert.KEY_DENY);
        assertNotNull(allowObj5);
        Object itemNamesRestrictionObj5 = allowObj5.get(AccessControlConstants.REP_ITEM_NAMES);
        assertTrue(itemNamesRestrictionObj5 instanceof JsonArray);
        assertEquals("item1", ((JsonArray)itemNamesRestrictionObj5).getString(0));
        assertEquals("item2", ((JsonArray)itemNamesRestrictionObj5).getString(1));
    }

    /**
     * Test method for {@link org.apache.sling.jcr.jackrabbit.accessmanager.impl.JsonConvert#addRestrictions(javax.json.JsonObjectBuilder, java.lang.String, java.util.Set)}.
     */
    @Test
    public void testAddRestrictions() {
        JsonObjectBuilder privilegeObj = Json.createObjectBuilder();
        String key = JsonConvert.KEY_ALLOW;
        Set<LocalRestriction> restrictions = new HashSet<>();
        restrictions.add(new LocalRestriction(rd(AccessControlConstants.REP_GLOB), val("/hello")));
        restrictions.add(new LocalRestriction(rd(AccessControlConstants.REP_ITEM_NAMES), vals("item1", "item2")));
        JsonConvert.addRestrictions(privilegeObj, key, restrictions);
        JsonObject build = privilegeObj.build();
        assertNotNull(build);
        JsonObject allowObj = build.getJsonObject(JsonConvert.KEY_ALLOW);
        assertNotNull(allowObj);
        Object globRestrictionObj = allowObj.get(AccessControlConstants.REP_GLOB);
        assertTrue(globRestrictionObj instanceof JsonString);
        assertEquals("/hello", ((JsonString)globRestrictionObj).getString());
        Object itemNamesRestrictionObj = allowObj.get(AccessControlConstants.REP_ITEM_NAMES);
        assertTrue(itemNamesRestrictionObj instanceof JsonArray);
        assertEquals("item1", ((JsonArray)itemNamesRestrictionObj).getString(0));
        assertEquals("item2", ((JsonArray)itemNamesRestrictionObj).getString(1));
    }

    /**
     * Test method for {@link org.apache.sling.jcr.jackrabbit.accessmanager.impl.JsonConvert#addTo(javax.json.JsonObjectBuilder, java.lang.String, java.lang.Object)}.
     */
    @Test
    public void testAddToJsonObjectBuilderStringObject() throws RepositoryException {
        JsonObjectBuilder builder = Json.createObjectBuilder();

        String key = JsonConvert.KEY_ALLOW;
        Function<JsonObject, Object> doubleFn = json -> json.getJsonNumber(key).doubleValue();
        Function<JsonObject, Object> bigDecimalFn = json -> json.getJsonNumber(key).bigDecimalValue();
        Function<JsonObject, Object> bigIntegerFn = json -> json.getJsonNumber(key).bigIntegerValue();
        Function<JsonObject, Object> longFn = json -> json.getJsonNumber(key).longValue();
        Function<JsonObject, Object> intFn = json -> json.getJsonNumber(key).intValue();
        Function<JsonObject, Object> booleanFn = json -> json.getBoolean(key);
        Function<JsonObject, Object> stringFn = json -> json.getString(key);
        Function<JsonObject, Object> privFn = json -> json.getJsonObject(key).getString("name");

        ValueFactory vf = ValueFactoryImpl.getInstance();
        // data to test [label, value, expectedValueFromJson, lookupFromJsonFn]
        Object[][] candidates = new Object[][] {
            // JCR Value types
            {"JCR double Value", vf.createValue((double)1.1), 1.1, doubleFn},
            {"JCR BigDecimal Value", vf.createValue(new BigDecimal("1.1")), new BigDecimal("1.1"), bigDecimalFn},
            {"JCR long Value", vf.createValue(1L), 1L, longFn},
            {"JCR boolean Value", vf.createValue(true), true, booleanFn},
            {"JCR string Value", vf.createValue("hello"), "hello", stringFn},

            // non-JCR values
            {"byte value", (byte)1, 1, intFn},
            {"short value", (short)1, 1, intFn},
            {"int value", 1, 1, intFn},
            {"long value", 1L, 1L, longFn},
            {"BigDecimal value", new BigDecimal("1.1"), new BigDecimal("1.1"), bigDecimalFn},
            {"BigInteger value", new BigInteger("1"), new BigInteger("1"), bigIntegerFn},
            {"true boolean value", true, true, booleanFn},
            {"false boolean value", false, false, booleanFn},
            {"float value", (float)1.1, (double)1.1, doubleFn},
            {"double value", 1.1, 1.1, doubleFn},
            {"string value", "hello", "hello", stringFn},
            {"privilege value", priv(PrivilegeConstants.JCR_READ), PrivilegeConstants.JCR_READ, privFn},
            {"object value", new StringBuilder().append("hello"), "hello", stringFn}
        };
        for (Object[] objects : candidates) {
            Object value = objects[1];
            JsonConvert.addTo(builder, key, value);
            JsonObject build = builder.build();
            assertNotNull(build);
            assertEquals(1, build.size());
            @SuppressWarnings("unchecked")
            Function<JsonObject, Object> supplier = (Function<JsonObject, Object>)objects[3];
            if (objects[2] instanceof Double) {
                double epsilon = 0.000001d;
                assertEquals(String.format("%s was not the expected value", objects[0]), (double)objects[2], (double)supplier.apply(build), epsilon);
            } else {
                assertEquals(String.format("%s was not the expected value", objects[0]), objects[2], supplier.apply(build));
            }
        }
    }

    /**
     * Test method for {@link org.apache.sling.jcr.jackrabbit.accessmanager.impl.JsonConvert#addTo(javax.json.JsonArrayBuilder, java.lang.Object)}.
     */
    @Test
    public void testAddToJsonArrayBuilderObject() {
        JsonArrayBuilder builder = Json.createArrayBuilder();

        Function<JsonArray, Object> doubleFn = json -> json.getJsonNumber(0).doubleValue();
        Function<JsonArray, Object> bigDecimalFn = json -> json.getJsonNumber(0).bigDecimalValue();
        Function<JsonArray, Object> bigIntegerFn = json -> json.getJsonNumber(0).bigIntegerValue();
        Function<JsonArray, Object> longFn = json -> json.getJsonNumber(0).longValue();
        Function<JsonArray, Object> intFn = json -> json.getJsonNumber(0).intValue();
        Function<JsonArray, Object> booleanFn = json -> json.getBoolean(0);
        Function<JsonArray, Object> stringFn = json -> json.getString(0);

        ValueFactory vf = ValueFactoryImpl.getInstance();
        // data to test [label, value, expectedValueFromJson, lookupFromJsonFn]
        Object[][] candidates = new Object[][] {
            // JCR Value types
            {"JCR double Value", vf.createValue((double)1.1), 1.1, doubleFn},
            {"JCR BigDecimal Value", vf.createValue(new BigDecimal("1.1")), new BigDecimal("1.1"), bigDecimalFn},
            {"JCR long Value", vf.createValue(1L), 1L, longFn},
            {"JCR boolean Value", vf.createValue(true), true, booleanFn},
            {"JCR string Value", vf.createValue("hello"), "hello", stringFn},

            // non-JCR values
            {"byte value", (byte)1, 1, intFn},
            {"short value", (short)1, 1, intFn},
            {"int value", 1, 1, intFn},
            {"long value", 1L, 1L, longFn},
            {"BigDecimal value", new BigDecimal("1.1"), new BigDecimal("1.1"), bigDecimalFn},
            {"BigInteger value", new BigInteger("1"), new BigInteger("1"), bigIntegerFn},
            {"true boolean value", true, true, booleanFn},
            {"false boolean value", false, false, booleanFn},
            {"float value", (float)1.1, (double)1.1, doubleFn},
            {"double value", 1.1, 1.1, doubleFn},
            {"string value", "hello", "hello", stringFn},
            {"object value", new StringBuilder().append("hello"), "hello", stringFn}
        };
        for (Object[] objects : candidates) {
            Object value = objects[1];
            JsonConvert.addTo(builder, value);
            JsonArray build = builder.build();
            assertNotNull(build);
            assertEquals(1, build.size());
            @SuppressWarnings("unchecked")
            Function<JsonArray, Object> supplier = (Function<JsonArray, Object>)objects[3];
            if (objects[2] instanceof Double) {
                double epsilon = 0.000001d;
                assertEquals(String.format("%s was not the expected value", objects[0]), (double)objects[2], (double)supplier.apply(build), epsilon);
            } else {
                assertEquals(String.format("%s was not the expected value", objects[0]), objects[2], supplier.apply(build));
            }
        }
    }

}
