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

public class JcrModifiableValueMapTest extends SlingRepositoryTestBase {

    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();
        String 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(), 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() {
        return new HelperData(new AtomicReference<>(), new AtomicReference<>());
    }

    private Map<String, Object> initialSet() {
        final Map<String, Object> values = new HashMap<>();
        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());
        assertEquals("The read stream is not what we wrote.", IOUtils.toString(valueMap2.get("binary", InputStream.class)), 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);
        assertSame(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<>();
        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<>();
        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());

    }

}