/*
 * 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 ModifiableValueMap modifiableValueMap2 = new JcrModifiableValueMap(this.rootNode, getHelperData());
        assertTrue("The read stream is not what we wrote.", IOUtils.toString(modifiableValueMap2.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 ModifiableValueMap pvm2 = new JcrModifiableValueMap(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 ModifiableValueMap pvm2 = new JcrModifiableValueMap(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 JcrModifiableValueMap(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 JcrModifiableValueMap(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 JcrModifiableValueMap(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 JcrModifiableValueMap(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());

    }

}