/*
 * 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 java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

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

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.assertTrue("Type of property '" + property + "' should have changed", valueMap.get(property).getClass().equals(testResult.expectedNewType));
                    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.assertEquals("Final map entries do NOT match", expectedMap.entrySet(), valueMap.entrySet());
        Assert.assertEquals("Final map keys do NOT match", expectedMap.keySet(), valueMap.keySet());
        Assert.assertTrue("Final map values do NOT match expected: <" + expectedMap.values() + "> but was: <" + valueMap.values() + ">", CollectionUtils.isEqualCollection(expectedMap.values(), valueMap.values()));
    }

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

    }

}
