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

}
