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

import static org.apache.sling.jcr.resource.internal.AssertCalendar.assertEqualsCalendar;

import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.io.Serializable;
import java.lang.reflect.Array;
import java.math.BigDecimal;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TimeZone;
import java.util.concurrent.atomic.AtomicReference;

import javax.jcr.Node;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import javax.jcr.Value;
import javax.jcr.ValueFactory;
import javax.jcr.nodetype.NodeType;

import org.apache.commons.io.IOUtils;
import org.apache.jackrabbit.util.Text;
import org.apache.sling.api.resource.ModifiableValueMap;
import org.apache.sling.api.resource.ValueMap;
import org.apache.sling.api.resource.external.URIProvider;
import org.apache.sling.commons.classloader.DynamicClassLoaderManager;
import org.apache.sling.jcr.resource.internal.helper.jcr.SlingRepositoryTestBase;

public class JcrModifiableValueMapTest extends SlingRepositoryTestBase {

    private String rootPath;

    private Node rootNode;

    public static final byte[] TEST_BYTE_ARRAY = {'T', 'e', 's', 't'};
    public static final String TEST_BYTE_ARRAY_TO_STRING = new String(TEST_BYTE_ARRAY);

    @Override
    protected void setUp() throws Exception {
        super.setUp();
        rootPath = "/test_" + System.currentTimeMillis();
        rootNode = getSession().getRootNode().addNode(rootPath.substring(1),
            "nt:unstructured");

        final Map<String, Object> values = this.initialSet();
        for(Map.Entry<String, Object> entry : values.entrySet()) {
            setProperty(rootNode, entry.getKey().toString(), entry.getValue());
        }
        getSession().save();
    }

    private void setProperty(final Node node,
            final String propertyName,
            final Object propertyValue)
    throws RepositoryException {
        if ( propertyValue == null ) {
            node.setProperty(propertyName, (String)null);
        } else if ( propertyValue.getClass().isArray() ) {
            final int length = Array.getLength(propertyValue);
            final Value[] setValues = new Value[length];
            for(int i=0; i<length; i++) {
                final Object value = Array.get(propertyValue, i);
                setValues[i] = createValue(value, node.getSession());
            }
            node.setProperty(propertyName, setValues);
        } else {
            node.setProperty(propertyName, createValue(propertyValue, node.getSession()));
        }
    }

    Value createValue(final Object value, final Session session)
            throws RepositoryException {
                Value val;
                ValueFactory fac = session.getValueFactory();
                if(value instanceof Calendar) {
                    val = fac.createValue((Calendar)value);
                } else if (value instanceof InputStream) {
                    val = fac.createValue(fac.createBinary((InputStream)value));
                } else if (value instanceof Node) {
                    val = fac.createValue((Node)value);
                } else if (value instanceof BigDecimal) {
                    val = fac.createValue((BigDecimal)value);
                } else if (value instanceof Long) {
                    val = fac.createValue((Long)value);
                } else if (value instanceof Short) {
                    val = fac.createValue((Short)value);
                } else if (value instanceof Integer) {
                    val = fac.createValue((Integer)value);
                } else if (value instanceof Number) {
                    val = fac.createValue(((Number)value).doubleValue());
                } else if (value instanceof Boolean) {
                    val = fac.createValue((Boolean) value);
                } else if ( value instanceof String ) {
                    val = fac.createValue((String)value);
                } else {
                    val = null;
                }
                return val;
            }

    @Override
    protected void tearDown() throws Exception {
        if (rootNode != null) {
            rootNode.remove();
            getSession().save();
        }
        super.tearDown();
    }

    private HelperData getHelperData() throws Exception {
        return new HelperData(new AtomicReference<DynamicClassLoaderManager>(), new AtomicReference<URIProvider[]>());
    }

    private Map<String, Object> initialSet() {
        final Map<String, Object> values = new HashMap<String, Object>();
        values.put("string", "test");
        values.put("long", 1L);
        values.put("bool", Boolean.TRUE);
        return values;
    }

    public void testStreams() throws Exception {
        final ModifiableValueMap pvm = new JcrModifiableValueMap(this.rootNode, getHelperData());
        InputStream stream = new ByteArrayInputStream(TEST_BYTE_ARRAY);
        pvm.put("binary", stream);
        getSession().save();
        final ValueMap valueMap2 = new JcrValueMap(this.rootNode, getHelperData());
        assertTrue("The read stream is not what we wrote.", IOUtils.toString(valueMap2.get("binary", InputStream.class)).equals
                (TEST_BYTE_ARRAY_TO_STRING));
    }

    public void testPut()
    throws Exception {
        getSession().refresh(false);
        final ModifiableValueMap pvm = new JcrModifiableValueMap(this.rootNode, getHelperData());
        assertContains(pvm, initialSet());
        assertNull(pvm.get("something"));

        // now put two values and check set again
        pvm.put("something", "Another value");
        pvm.put("string", "overwrite");

        final Map<String, Object> currentlyStored = this.initialSet();
        currentlyStored.put("something", "Another value");
        currentlyStored.put("string", "overwrite");
        assertContains(pvm, currentlyStored);

        getSession().save();
        assertContains(pvm, currentlyStored);

        final ValueMap pvm2 = new JcrValueMap(this.rootNode, getHelperData());
        assertContains(pvm2, currentlyStored);
    }

    public void testRemove()
    throws Exception {
        getSession().refresh(false);
        final ModifiableValueMap pvm = new JcrModifiableValueMap(this.rootNode, getHelperData());

        final String key = "removeMe";
        final Long longValue = 5L;

        pvm.put(key, longValue);

        final Object removedValue = pvm.remove(key);
        assertTrue(removedValue instanceof Long);
        assertTrue(removedValue == longValue);
        assertFalse(pvm.containsKey(key));
    }

    public void testSerializable()
    throws Exception {
        this.rootNode.getSession().refresh(false);
        final ModifiableValueMap pvm = new JcrModifiableValueMap(this.rootNode, getHelperData());
        assertContains(pvm, initialSet());
        assertNull(pvm.get("something"));

        // now put a serializable object
        final List<String> strings = new ArrayList<String>();
        strings.add("a");
        strings.add("b");
        pvm.put("something", strings);

        // check if we get the list again
        @SuppressWarnings("unchecked")
        final List<String> strings2 = (List<String>) pvm.get("something");
        assertEquals(strings, strings2);

        getSession().save();

        final ValueMap pvm2 = new JcrValueMap(this.rootNode, getHelperData());
        // check if we get the list again
        @SuppressWarnings("unchecked")
        final List<String> strings3 = (List<String>) pvm2.get("something", Serializable.class);
        assertEquals(strings, strings3);

    }

    public void testExceptions() throws Exception {
        this.rootNode.getSession().refresh(false);
        final ModifiableValueMap pvm = new JcrModifiableValueMap(this.rootNode, getHelperData());
        try {
            pvm.put(null, "something");
            fail("Put with null key");
        } catch (NullPointerException iae) {}
        try {
            pvm.put("something", null);
            fail("Put with null value");
        } catch (NullPointerException iae) {}
        try {
            pvm.put("something", pvm);
            fail("Put with non serializable");
        } catch (IllegalArgumentException iae) {}
    }

    private Set<String> getMixinNodeTypes(final Node node) throws RepositoryException {
        final Set<String> mixinTypes = new HashSet<String>();
        for(final NodeType mixinNodeType : node.getMixinNodeTypes() ) {
            mixinTypes.add(mixinNodeType.getName());
        }
        return mixinTypes;
    }

    public void testMixins() throws Exception {
        this.rootNode.getSession().refresh(false);
        final Node testNode = this.rootNode.addNode("testMixins" + System.currentTimeMillis());
        testNode.getSession().save();
        final ModifiableValueMap pvm = new JcrModifiableValueMap(testNode, getHelperData());

        final String[] types = pvm.get("jcr:mixinTypes", String[].class);
        final Set<String> exNodeTypes = getMixinNodeTypes(testNode);

        assertEquals(exNodeTypes.size(), (types == null ? 0 : types.length));
        if ( types != null ) {
            for(final String name : types) {
                assertTrue(exNodeTypes.contains(name));
            }
            String[] newTypes = new String[types.length + 1];
            System.arraycopy(types, 0, newTypes, 0, types.length);
            newTypes[types.length] = "mix:referenceable";
            pvm.put("jcr:mixinTypes", newTypes);
        } else {
            pvm.put("jcr:mixinTypes", "mix:referenceable");
        }
        getSession().save();

        final Set<String> newNodeTypes = getMixinNodeTypes(testNode);
        assertEquals(newNodeTypes.size(), exNodeTypes.size() + 1);
    }

    private static final String TEST_PATH = "a<a";

    private static final String VALUE = "value";
    private static final String VALUE1 = "value";
    private static final String VALUE2 = "value";
    private static final String VALUE3 = "my title";
    private static final String PROP1 = "-prop";
    private static final String PROP2 = "1prop";
    private static final String PROP3 = "jcr:title";

    public void testNamesReverse() throws Exception {
        this.rootNode.getSession().refresh(false);

        final Node testNode = this.rootNode.addNode("nameTest" + System.currentTimeMillis());
        testNode.getSession().save();
        final ModifiableValueMap pvm = new JcrModifiableValueMap(testNode, getHelperData());
        pvm.put(TEST_PATH, VALUE);
        pvm.put(PROP1, VALUE1);
        pvm.put(PROP2, VALUE2);
        pvm.put(PROP3, VALUE3);
        getSession().save();

        // read with property map
        final ValueMap vm = new JcrValueMap(testNode, getHelperData());
        assertEquals(VALUE, vm.get(TEST_PATH));
        assertEquals(VALUE1, vm.get(PROP1));
        assertEquals(VALUE2, vm.get(PROP2));
        assertEquals(VALUE3, vm.get(PROP3));

        // read properties
        assertEquals(VALUE, testNode.getProperty(TEST_PATH).getString());
        assertEquals(VALUE1, testNode.getProperty(PROP1).getString());
        assertEquals(VALUE2, testNode.getProperty(PROP2).getString());
        assertEquals(VALUE3, testNode.getProperty(PROP3).getString());
    }

    /**
     * Checks property names encoding, see SLING-2502.
     */
    public void testNamesUpdate() throws Exception {
        this.rootNode.getSession().refresh(false);

        final Node testNode = this.rootNode.addNode("nameUpdateTest"
                + System.currentTimeMillis());
        testNode.setProperty(PROP3, VALUE);
        testNode.getSession().save();

        final ModifiableValueMap pvm = new JcrModifiableValueMap(testNode, getHelperData());
        pvm.put(PROP3, VALUE3);
        pvm.put("jcr:a:b", VALUE3);
        pvm.put("jcr:", VALUE3);
        getSession().save();

        // read with property map
        final ValueMap vm = new JcrValueMap(testNode, getHelperData());
        assertEquals(VALUE3, vm.get(PROP3));
        assertEquals(VALUE3, vm.get("jcr:a:b"));
        assertEquals(VALUE3, vm.get("jcr:"));

        // read properties
        assertEquals(VALUE3, testNode.getProperty(PROP3).getString());
        assertEquals(VALUE3, testNode.getProperty("jcr:"+Text.escapeIllegalJcrChars("a:b")).getString());
        assertEquals(VALUE3, testNode.getProperty(Text.escapeIllegalJcrChars("jcr:")).getString());
        assertFalse(testNode.hasProperty(Text.escapeIllegalJcrChars(PROP3)));
        assertFalse(testNode.hasProperty(Text.escapeIllegalJcrChars("jcr:a:b")));
    }

    /**
     * Check that the value map contains all supplied values
     */
    private void assertContains(ValueMap map, Map<String, Object> values) {
        for(Map.Entry<String, Object> entry : values.entrySet()) {
            final Object stored = map.get(entry.getKey());
            assertEquals(values.get(entry.getKey()), stored);
        }
    }

    /**
     * Test date conversions from Date to Calendar and vice versa when reading or writing from value maps.
     */
    public void testDateConversion() throws Exception {
        this.rootNode.getSession().refresh(false);

        // prepare some date values
        Date dateValue1 = new Date(10000);
        Calendar calendarValue1 = Calendar.getInstance();
        calendarValue1.setTime(dateValue1);

        Date dateValue2 = new Date(20000);
        Calendar calendarValue2 = Calendar.getInstance();
        calendarValue2.setTime(dateValue2);

        Date dateValue3 = new Date(30000);
        Calendar calendarValue3 = Calendar.getInstance();
        calendarValue3.setTime(dateValue3);

        // write property
        final Node testNode = this.rootNode.addNode("dateConversionTest" + System.currentTimeMillis());
        testNode.setProperty(PROP1, calendarValue1);
        testNode.getSession().save();

        // write with property map
        final ModifiableValueMap pvm = new JcrModifiableValueMap(testNode, getHelperData());
        pvm.put(PROP2, dateValue2);
        pvm.put(PROP3, calendarValue3);
        getSession().save();

        // read with property map
        final ValueMap vm = new JcrValueMap(testNode, getHelperData());
        assertEquals(dateValue1, vm.get(PROP1, Date.class));
        assertEqualsCalendar(calendarValue1, vm.get(PROP1, Calendar.class));
        assertEquals(dateValue2, vm.get(PROP2, Date.class));
        assertEqualsCalendar(calendarValue2, vm.get(PROP2, Calendar.class));
        assertEquals(dateValue3, vm.get(PROP3, Date.class));
        assertEqualsCalendar(calendarValue3, vm.get(PROP3, Calendar.class));

        // check types
        assertTrue(vm.get(PROP1) instanceof Calendar);
        assertTrue(vm.get(PROP2) instanceof InputStream);
        assertTrue(vm.get(PROP3) instanceof Calendar);

        // read properties
        assertEqualsCalendar(calendarValue1, testNode.getProperty(PROP1).getDate());
        assertEqualsCalendar(calendarValue3, testNode.getProperty(PROP3).getDate());

    }

    /**
     * Test conversions involving ZonedDateTime
     */
    public void testZonedDateTimeConversions() throws Exception {
        this.rootNode.getSession().refresh(false);

        String dateAsIso8601 = "2019-07-04T14:05:37.123+02:00";
        ZonedDateTime zonedDateTime = ZonedDateTime.parse(dateAsIso8601, DateTimeFormatter.ISO_OFFSET_DATE_TIME);
        Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone(zonedDateTime.getOffset()));
        calendar.setTimeInMillis(zonedDateTime.toInstant().toEpochMilli());

        // write property
        final Node testNode = this.rootNode.addNode("dateConversionTest" + System.currentTimeMillis());
        testNode.setProperty(PROP1, calendar);
        testNode.getSession().save();

        // write with property map
        final ModifiableValueMap pvm = new JcrModifiableValueMap(testNode, getHelperData());
        pvm.put(PROP2, zonedDateTime);
        pvm.put(PROP3, dateAsIso8601);
        getSession().save();

        // read with property map
        final ValueMap vm = new JcrValueMap(testNode, getHelperData());

        // check types
        assertTrue(vm.get(PROP1) instanceof Calendar);
        assertTrue(vm.get(PROP2) instanceof Calendar);
        assertTrue(vm.get(PROP3) instanceof String);

        // to ZonedDateTime
        assertEquals(zonedDateTime, vm.get(PROP1, ZonedDateTime.class)); // from Calendar
        assertEquals(zonedDateTime, vm.get(PROP2, ZonedDateTime.class)); // from ZonedDateTime
        assertEquals(zonedDateTime, vm.get(PROP3, ZonedDateTime.class)); // from ISO-8601 String

        // from ZonedDateTime
        assertEqualsCalendar(calendar, vm.get(PROP2, Calendar.class)); // to Calendar
        assertEquals(calendar.getTime(), vm.get(PROP2, Date.class));   // to Date
        assertEquals(dateAsIso8601, vm.get(PROP2, String.class));      // to String


        // read properties
        assertEqualsCalendar(calendar, testNode.getProperty(PROP1).getDate());
        assertEqualsCalendar(calendar, testNode.getProperty(PROP2).getDate());
        assertEqualsCalendar(calendar, testNode.getProperty(PROP3).getDate());

    }

}