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

import org.apache.sling.api.resource.ValueMap;
import org.junit.Assert;
import org.junit.Test;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import static org.hamcrest.Matchers.containsInAnyOrder;

public class CompositeValueMapTest {

    // Test property names
    private static final String PROP_NAME_UNCHANGED = "unchangedProp";
    private static final String PROP_NAME_OVERRIDDEN = "overriddenProp";
    private static final String PROP_NAME_NEW_TYPE = "newTypeProp";
    private static final String PROP_NAME_ADDED = "addedProp";
    private static final String PROP_NAME_DOES_NOT_EXIST = "doesNotExistProp";

    // Default resource's property values
    private static final String PROP_DEFAULT_UNCHANGED = "Default value of property '" + PROP_NAME_UNCHANGED + "'";
    private static final String PROP_DEFAULT_OVERRIDDEN = "Default value of property '" + PROP_NAME_OVERRIDDEN + "'";
    private static final String PROP_DEFAULT_NEW_TYPE = "10";

    // Extended resource's property values
    private static final String PROP_EXTENDED_OVERRIDDEN = "Extended value of property '" + PROP_NAME_OVERRIDDEN + "'";
    private static final Long PROP_EXTENDED_NEW_TYPE = 10L;
    private static final String PROP_EXTENDED_ADDED = "Extended value of property '" + PROP_NAME_ADDED + "'";

    private Map<String, Object> defaultProps = getDefaultProps();
    private Map<String, Object> extendedProps = getExtendedProps();

    @Test
    public void testMerge() throws Exception {
        // Get value map for extended node using default node as defaults
        CompositeValueMap valueMap = new CompositeValueMap(
                getExtendedProps(),
                getDefaultProps()
        );

        Set<CompositeValueMapTestResult> expectations = new HashSet<CompositeValueMapTestResult>();
        expectations.add(new CompositeValueMapTestResult(PROP_NAME_UNCHANGED));
        expectations.add(new CompositeValueMapTestResult(PROP_NAME_OVERRIDDEN));
        expectations.add(new CompositeValueMapTestResult(PROP_NAME_NEW_TYPE, false, PROP_EXTENDED_NEW_TYPE.getClass()));
        expectations.add(new CompositeValueMapTestResult(PROP_NAME_ADDED));
        expectations.add(new CompositeValueMapTestResult(PROP_NAME_DOES_NOT_EXIST));

        verifyResults(valueMap, expectations);
    }

    @Test
    public void testMergeNoDefaults() throws Exception {
        // Get value map for extended node using an empty default
        CompositeValueMap valueMap = new CompositeValueMap(
                getExtendedProps(),
                null
        );

        Set<CompositeValueMapTestResult> expectations = new HashSet<CompositeValueMapTestResult>();
        expectations.add(new CompositeValueMapTestResult(PROP_NAME_UNCHANGED, true)); // Property won't exist as there is no default
        expectations.add(new CompositeValueMapTestResult(PROP_NAME_OVERRIDDEN));
        expectations.add(new CompositeValueMapTestResult(PROP_NAME_NEW_TYPE, false, PROP_EXTENDED_NEW_TYPE.getClass()));
        expectations.add(new CompositeValueMapTestResult(PROP_NAME_ADDED));
        expectations.add(new CompositeValueMapTestResult(PROP_NAME_DOES_NOT_EXIST));

        verifyResults(valueMap, expectations);
    }

    @Test
    public void testOverride() throws Exception {
        // Get value map for extended node using default node as defaults
        // and override only mode
        CompositeValueMap valueMap = new CompositeValueMap(
                getExtendedProps(),
                getDefaultProps(),
                false
        );

        Set<CompositeValueMapTestResult> expectations = new HashSet<CompositeValueMapTestResult>();
        expectations.add(new CompositeValueMapTestResult(PROP_NAME_UNCHANGED));
        expectations.add(new CompositeValueMapTestResult(PROP_NAME_OVERRIDDEN));
        expectations.add(new CompositeValueMapTestResult(PROP_NAME_NEW_TYPE, false, PROP_EXTENDED_NEW_TYPE.getClass()));
        expectations.add(new CompositeValueMapTestResult(PROP_NAME_ADDED, true)); // Property won't exist as there is no default and it's an override
        expectations.add(new CompositeValueMapTestResult(PROP_NAME_DOES_NOT_EXIST));

        verifyResults(valueMap, expectations);
    }

    @Test
    public void testOverrideNoDefaults() throws Exception {
        // Get value map for extended node using an empty default
        // and override only mode
        CompositeValueMap valueMap = new CompositeValueMap(
                getExtendedProps(),
                null,
                false
        );

        Assert.assertTrue("Final map should be empty", valueMap.isEmpty());
    }

    private ValueMap getDefaultProps() {
        final Map<String, Object> defaultProps = new HashMap<String, Object>();

        defaultProps.put(PROP_NAME_UNCHANGED, PROP_DEFAULT_UNCHANGED);
        defaultProps.put(PROP_NAME_OVERRIDDEN, PROP_DEFAULT_OVERRIDDEN);
        defaultProps.put(PROP_NAME_NEW_TYPE, PROP_DEFAULT_NEW_TYPE);

        return new ValueMapDecorator(defaultProps);
    }

    private ValueMap getExtendedProps() {
        final Map<String, Object> defaultProps = new HashMap<String, Object>();

        defaultProps.put(PROP_NAME_OVERRIDDEN, PROP_EXTENDED_OVERRIDDEN);
        defaultProps.put(PROP_NAME_NEW_TYPE, PROP_EXTENDED_NEW_TYPE);
        defaultProps.put(PROP_NAME_ADDED, PROP_EXTENDED_ADDED);

        return new ValueMapDecorator(defaultProps);
    }

    private void verifyResults(CompositeValueMap valueMap, Set<CompositeValueMapTestResult> expectations) {
        Map<String, Object> expectedMap = new HashMap<String, Object>();

        int expectedSize = 0;
        for (CompositeValueMapTestResult testResult : expectations) {
            String property = testResult.propertyName;

            if (testResult.doesNotExist()) {
                Assert.assertFalse("Property '" + property + "' should NOT exist", valueMap.containsKey(property));

            } else if (testResult.shouldBeDeleted()) {
                Assert.assertFalse("Property '" + property + "' should NOT be part of the final map", valueMap.containsKey(property));
                Assert.assertNull("Property '" + property + "' should be null", valueMap.get(property));

            } else {
                Assert.assertTrue("Property '" + property + "' should be part of the final map", valueMap.containsKey(property));
                expectedSize++;

                if (testResult.shouldBeUnchanged()) {
                    Assert.assertEquals("Property '" + property + "' should NOT have changed", testResult.defaultValue, valueMap.get(property));
                    expectedMap.put(property, testResult.defaultValue);
                }

                if (testResult.shouldBeOverriden()) {
                    Assert.assertEquals("Property '" + property + "' should have changed", testResult.extendedValue, valueMap.get(property));
                    expectedMap.put(property, testResult.extendedValue);
                }

                if (testResult.shouldHaveNewType()) {
                    Assert.assertEquals("Type of property '" + property + "' should have changed",testResult.expectedNewType, valueMap.get(property).getClass());
                    expectedMap.put(property, testResult.extendedValue);
                }

                if (testResult.shouldBeAdded()) {
                    Assert.assertEquals("Property '" + property + "' should have been added", testResult.extendedValue, valueMap.get(property));
                    expectedMap.put(property, testResult.extendedValue);
                }
            }
        }

        Assert.assertEquals("Final map size does NOT match", expectedSize, valueMap.size());
        Assert.assertThat("Final map keys do NOT match", valueMap.keySet(), containsInAnyOrder(expectedMap.keySet().toArray()));
        Assert.assertThat("Final map values do NOT match", valueMap.values(), containsInAnyOrder(expectedMap.values().toArray()));
        Assert.assertThat("Final map entries do NOT match", valueMap.entrySet(), containsInAnyOrder(expectedMap.entrySet().toArray()));
    }

    /**
     * <code>CompositeValueMapTestResult</code> is an internal helper to analyze
     * test result and check if the value retrieved from the map matches the
     * expected value.
     */
    private class CompositeValueMapTestResult {
        private final String propertyName;
        private final Object defaultValue;
        private final Object extendedValue;
        private final boolean shouldBeDeleted;
        private final Class<?> expectedNewType;

        private CompositeValueMapTestResult(String propertyName) {
            this(propertyName, false);
        }

        private CompositeValueMapTestResult(String propertyName, boolean shouldBeDeleted) {
            this(propertyName, shouldBeDeleted, null);
        }

        private CompositeValueMapTestResult(String propertyName, boolean shouldBeDeleted, Class<?> expectedNewType) {
            this.propertyName = propertyName;
            this.defaultValue = defaultProps.get(propertyName);
            this.extendedValue = extendedProps.get(propertyName);
            this.shouldBeDeleted = shouldBeDeleted;
            this.expectedNewType = expectedNewType;
        }

        /**
         * Checks if the value should not have changed
         * @return <code>true</code> if the value should not have changed
         */
        boolean shouldBeUnchanged() {
            return defaultValue != null && extendedValue == null;
        }

        /**
         * Checks if the value should have been overridden
         * @return <code>true</code> if the value should have been overridden
         */
        boolean shouldBeOverriden() {
            return defaultValue != null && extendedValue != null;
        }

        /**
         * Checks if the value should have a new type
         * @return <code>true</code> if the value should have a new type
         */
        boolean shouldHaveNewType() {
            return expectedNewType != null;
        }

        /**
         * Checks if the property should have been added
         * @return <code>true</code> if the property should have been added
         */
        boolean shouldBeAdded() {
            return defaultValue == null && extendedValue != null;
        }

        /**
         * Checks if the property should have been deleted
         * @return <code>true</code> if the property should have been deleted
         */
        boolean shouldBeDeleted() {
            return shouldBeDeleted;
        }

        /**
         * Checks if the property should not exist
         * @return <code>true</code> if the property should not exist
         */
        boolean doesNotExist() {
            return defaultValue == null && extendedValue == null;
        }

    }

}
