/*
 * 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.testing.mock.sling.builder;

import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

import org.apache.sling.api.resource.ValueMap;
import org.apache.sling.api.wrappers.ValueMapDecorator;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.osgi.annotation.versioning.ProviderType;

/**
 * {@link ValueMap} that does not support changing its content.
 * <p>
 * All methods that may change the content will throw a
 * {@link UnsupportedOperationException}.
 * </p>
 * <p>
 * Static convenience methods provide similar behavior as Guava ImmutableMap
 * variants.
 * </p>
 */
@ProviderType
public final class ImmutableValueMap implements ValueMap {

    private final ValueMap map;

    /**
     * @param map Value map
     */
    ImmutableValueMap(@NotNull ValueMap map) {
        this.map = map;
    }

    /**
     * @param map Map
     */
    ImmutableValueMap(@NotNull Map<String, Object> map) {
        this.map = new ValueMapDecorator(map);
    }

    @Override
    public @Nullable <T> T get(@NotNull String name, @NotNull Class<T> type) {
        return this.map.get(name, type);
    }

    @Override
    public @NotNull <T> T get(@NotNull String name, @NotNull T defaultValue) {
        return this.map.get(name, defaultValue);
    }

    @Override
    public int size() {
        return this.map.size();
    }

    @Override
    public boolean isEmpty() {
        return this.map.isEmpty();
    }

    @Override
    public boolean containsKey(Object key) {
        return this.map.containsKey(key);
    }

    @Override
    public boolean containsValue(Object value) {
        return this.map.containsValue(value);
    }

    @Override
    public Object get(Object key) {
        return this.map.get(key);
    }

    @Override
    public Set<String> keySet() {
        return this.map.keySet();
    }

    @Override
    public Collection<Object> values() {
        return this.map.values();
    }

    @Override
    public Set<Entry<String, Object>> entrySet() {
        return Collections.unmodifiableSet(this.map.entrySet());
    }

    @Override
    public int hashCode() {
        return this.map.hashCode();
    }

    @Override
    public boolean equals(Object obj) {
        if (!(obj instanceof ImmutableValueMap)) {
            return false;
        }
        return this.map.entrySet().equals(((ImmutableValueMap) obj).map.entrySet());
    }

    @Override
    public String toString() {
        return map.toString();
    }

    // mutable operations not supported
    /**
     * @deprecated Unsupported operation
     */
    @Override
    @Deprecated
    public Object put(String key, Object value) {
        throw new UnsupportedOperationException();
    }

    /**
     * @deprecated Unsupported operation
     */
    @Override
    @Deprecated
    public Object remove(Object key) {
        throw new UnsupportedOperationException();
    }

    /**
     * @deprecated Unsupported operation
     */
    @Override
    @Deprecated
    public void putAll(Map<? extends String, ? extends Object> m) {
        throw new UnsupportedOperationException();
    }

    /**
     * @deprecated Unsupported operation
     */
    @Override
    @Deprecated
    public void clear() {
        throw new UnsupportedOperationException();
    }

    /**
     * Returns the empty map. This map behaves and performs comparably to
     * {@link Collections#emptyMap}, and is preferable mainly for consistency
     * and maintainability of your code.
     * @return ImmutableValueMap
     */
    public static @NotNull ImmutableValueMap of() {
        return new ImmutableValueMap(ValueMap.EMPTY);
    }

    /**
     * Returns an immutable map containing a single entry. This map behaves and
     * performs comparably to {@link Collections#singletonMap} but will not
     * accept a null key or value. It is preferable mainly for consistency and
     * maintainability of your code.
     * @param k1 Key 1
     * @param v1 Value 1
     * @return ImmutableValueMap
     */
    @SuppressWarnings("null")
    public static @NotNull ImmutableValueMap of(@NotNull String k1, @NotNull Object v1) {
        return new ImmutableValueMap(Collections.singletonMap(k1, v1));
    }

    /**
     * Returns an immutable map containing the given entries, in order.
     * @param k1 Key 1
     * @param v1 Value 1
     * @param k2 Key 2
     * @param v2 Value 2
     * @return ImmutableValueMap
     * @throws IllegalArgumentException if duplicate keys are provided
     */
    public static @NotNull ImmutableValueMap of(
            @NotNull String k1, @NotNull Object v1, @NotNull String k2, @NotNull Object v2) {
        Map<String, Object> map = new HashMap<>();
        map.put(k1, v1);
        map.put(k2, v2);
        return new ImmutableValueMap(map);
    }

    /**
     * Returns an immutable map containing the given entries, in order.
     * @param k1 Key 1
     * @param v1 Value 1
     * @param k2 Key 2
     * @param v2 Value 2
     * @param k3 Key 3
     * @param v3 Value 3
     * @return ImmutableValueMap
     * @throws IllegalArgumentException if duplicate keys are provided
     */
    public static @NotNull ImmutableValueMap of(
            @NotNull String k1,
            @NotNull Object v1,
            @NotNull String k2,
            @NotNull Object v2,
            @NotNull String k3,
            @NotNull Object v3) {
        Map<String, Object> map = new HashMap<>();
        map.put(k1, v1);
        map.put(k2, v2);
        map.put(k3, v3);
        return new ImmutableValueMap(map);
    }

    /**
     * Returns an immutable map containing the given entries, in order.
     * @param k1 Key 1
     * @param v1 Value 1
     * @param k2 Key 2
     * @param v2 Value 2
     * @param k3 Key 3
     * @param v3 Value 3
     * @param k4 Key 4
     * @param v4 Value 4
     * @return ImmutableValueMap
     * @throws IllegalArgumentException if duplicate keys are provided
     */
    public static @NotNull ImmutableValueMap of( // NOPMD
            @NotNull String k1,
            @NotNull Object v1,
            @NotNull String k2,
            @NotNull Object v2,
            @NotNull String k3,
            @NotNull Object v3,
            @NotNull String k4,
            @NotNull Object v4) {
        Map<String, Object> map = new HashMap<>();
        map.put(k1, v1);
        map.put(k2, v2);
        map.put(k3, v3);
        map.put(k4, v4);
        return new ImmutableValueMap(map);
    }

    /**
     * Returns an immutable map containing the given entries, in order.
     * @param k1 Key 1
     * @param v1 Value 1
     * @param k2 Key 2
     * @param v2 Value 2
     * @param k3 Key 3
     * @param v3 Value 3
     * @param k4 Key 4
     * @param v4 Value 4
     * @param k5 Key 5
     * @param v5 Value 5
     * @return ImmutableValueMap
     * @throws IllegalArgumentException if duplicate keys are provided
     */
    public static ImmutableValueMap of( // NOPMD
            @NotNull String k1,
            @NotNull Object v1,
            @NotNull String k2,
            @NotNull Object v2,
            @NotNull String k3,
            @NotNull Object v3,
            @NotNull String k4,
            @NotNull Object v4,
            @NotNull String k5,
            @NotNull Object v5) {
        Map<String, Object> map = new HashMap<>();
        map.put(k1, v1);
        map.put(k2, v2);
        map.put(k3, v3);
        map.put(k4, v4);
        map.put(k5, v5);
        return new ImmutableValueMap(map);
    }

    // looking for of() with > 5 entries? Use the builder instead.

    /**
     * Returns a new builder. The generated builder is equivalent to the builder
     * created by the {@link Builder} constructor.
     * @return Builder
     */
    public static @NotNull Builder builder() {
        return new Builder();
    }

    /**
     * Returns an immutable map containing the same entries as {@code map}. If
     * {@code map} somehow contains entries with duplicate keys (for example, if
     * it is a {@code SortedMap} whose comparator is not <i>consistent with
     * equals</i>), the results of this method are undefined.
     * <p>
     * Despite the method name, this method attempts to avoid actually copying
     * the data when it is safe to do so. The exact circumstances under which a
     * copy will or will not be performed are undocumented and subject to
     * change.
     * </p>
     * @param map Map
     * @return ImmutableValueMap
     * @throws NullPointerException if any key or value in {@code map} is null
     */
    public static @NotNull ImmutableValueMap copyOf(@NotNull Map<String, Object> map) {
        if (map instanceof ValueMap) {
            return new ImmutableValueMap((ValueMap) map);
        } else {
            return new ImmutableValueMap(map);
        }
    }

    /**
     * Builder interface for {@link ImmutableValueMap}.
     */
    public static final class Builder {

        private final @NotNull Map<String, Object> map = new HashMap<>();

        /**
         * Associates {@code key} with {@code value} in the built map. Duplicate
         * keys are not allowed, and will cause {@link #build} to fail.
         * @param key Key
         * @param value value
         * @return this
         */
        public @NotNull Builder put(@NotNull String key, @NotNull Object value) {
            map.put(key, value);
            return this;
        }

        /**
         * Adds the given {@code entry} to the map, making it immutable if
         * necessary. Duplicate keys are not allowed, and will cause
         * {@link #build} to fail.
         * @param entry Entry
         * @return this
         */
        public @NotNull Builder put(@NotNull Entry<String, Object> entry) {
            return put(entry.getKey(), entry.getValue());
        }

        /**
         * Associates all of the given map's keys and values in the built map.
         * Duplicate keys are not allowed, and will cause {@link #build} to
         * fail.
         * @param value Value
         * @return this
         * @throws NullPointerException if any key or value in {@code map} is
         *             null
         */
        public @NotNull Builder putAll(@NotNull Map<String, Object> value) {
            map.putAll(value);
            return this;
        }

        /**
         * Returns a newly-created immutable map.
         * @return ImmutableValueMap
         * @throws IllegalArgumentException if duplicate keys were added
         */
        public @NotNull ImmutableValueMap build() {
            if (map.isEmpty()) {
                return ImmutableValueMap.of();
            } else {
                return new ImmutableValueMap(map);
            }
        }
    }
}
