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

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

import org.jetbrains.annotations.Nullable;
import org.jetbrains.annotations.NotNull;

/**
 * The <code>ResourceMetadata</code> interface defines the API for the
 * metadata of a Sling {@link Resource}. Essentially the resource's metadata is
 * just a map of objects indexed by string keys.
 * <p>
 * The actual contents of the meta data map is implementation specific with the
 * exception of the {@link #RESOLUTION_PATH sling.resolutionPath} property which
 * must be provided by all implementations and contain the part of the request
 * URI used to resolve the resource. The type of this property value is defined
 * to be <code>String</code>.
 * <p>
 * Note, that the prefix <em>sling.</em> to key names is reserved for the
 * Sling implementation.
 *
 * Once a resource is returned by the {@link ResourceResolver}, the resource
 * metadata is made read-only and therefore can't be changed by client code!
 */
public class ResourceMetadata extends HashMap<String, Object> {

    private static final long serialVersionUID = 4692666752269523738L;

    /**
     * The name of the required property providing the part of the request URI
     * which was used to the resolve the resource to which the meta data
     * instance belongs (value is "sling.resolutionPath").
     */
    public static final String RESOLUTION_PATH = "sling.resolutionPath";

    /**
     * The name of the required property providing the part of the request URI
     * which was not used to the resolve the resource to which the meta data
     * instance belongs (value is "sling.resolutionPathInfo"). The value of this
     * property concatenated to the value of the
     * {@link #RESOLUTION_PATH sling.resolutionPath} property returns the
     * original request URI leading to the resource.
     * <p>
     * This property is optional. If missing, it should be assumed equal to an
     * empty string.
     *
     * @since 2.0.4 (Sling API Bundle 2.0.4)
     */
    public static final String RESOLUTION_PATH_INFO = "sling.resolutionPathInfo";

    /**
     * The name of the optional property providing the content type of the
     * resource if the resource is streamable (value is "sling.contentType").
     * This property may be missing if the resource is not streamable or if the
     * content type is not known.
     */
    public static final String CONTENT_TYPE = "sling.contentType";

    /**
     * The name of the optional property providing the content length of the
     * resource if the resource is streamable (value is "sling.contentLength").
     * This property may be missing if the resource is not streamable or if the
     * content length is not known.
     * <p>
     * Note, that unlike the other properties, this property may be set only
     * after the resource has successfully been adapted to an
     * <code>InputStream</code> for performance reasons.
     */
    public static final String CONTENT_LENGTH = "sling.contentLength";

    /**
     * The name of the optional property providing the character encoding of the
     * resource if the resource is streamable and contains character data (value
     * is "sling.characterEncoding"). This property may be missing if the
     * resource is not streamable or if the character encoding is not known.
     */
    public static final String CHARACTER_ENCODING = "sling.characterEncoding";

    /**
     * Returns the creation time of this resource in the repository in
     * milliseconds (value is "sling.creationTime"). The type of this property
     * is <code>java.lang.Long</code>. The property may be missing if the
     * resource is not streamable or if the creation time is not known.
     */
    public static final String CREATION_TIME = "sling.creationTime";

    /**
     * Returns the last modification time of this resource in the repository in
     * milliseconds (value is "sling.modificationTime"). The type of this
     * property is <code>java.lang.Long</code>. The property may be missing
     * if the resource is not streamable or if the last modification time is not
     * known.
     */
    public static final String MODIFICATION_TIME = "sling.modificationTime";

    /**
     * Returns whether the resource resolver should continue to search for a
     * resource.
     * A resource provider can set this flag to indicate that the resource
     * resolver should search for a provider with a lower priority. If it
     * finds a resource using such a provider, that resource is returned
     * instead. If none is found this resource is returned.
     * This flag should never be manipulated by application code!
     * The value of this property has no meaning, the resource resolver
     * just checks whether this flag is set or not.
     * @since 2.2 (Sling API Bundle 2.2.0)
     * @deprecated This flag is not supported anymore when implementing the SPI
     *             based {@code org.apache.sling.spi.resource.provider.ResourceProvider}
     */
    public static final String INTERNAL_CONTINUE_RESOLVING = ":org.apache.sling.resource.internal.continue.resolving";

    /**
     * Returns a map containing parameters added to path after semicolon.
     * For instance, map for path <code>/content/test;v='1.2.3'.html</code>
     * will contain one entry key <code>v</code> and value <code>1.2.3</code>.
     */
    public static final String PARAMETER_MAP = "sling.parameterMap";

    private boolean isReadOnly = false;

    /**
     * Sets the {@link #CHARACTER_ENCODING} property to <code>encoding</code>
     * if not <code>null</code>.
     * @param encoding The encoding
     */
    public void setCharacterEncoding(String encoding) {
        if (encoding != null) {
            put(CHARACTER_ENCODING, encoding);
        }
    }

    /**
     * Returns the {@link #CHARACTER_ENCODING} property if not <code>null</code>
     * and a <code>String</code> instance. Otherwise <code>null</code> is
     * returned.
     * @return The character encoding
     */
    public @Nullable String getCharacterEncoding() {
        Object value = get(CHARACTER_ENCODING);
        if (value instanceof String) {
            return (String) value;
        }

        return null;
    }

    /**
     * Sets the {@link #CONTENT_TYPE} property to <code>contentType</code> if
     * not <code>null</code>.
     * @param contentType The content type
     */
    public void setContentType(String contentType) {
        if (contentType != null) {
            put(CONTENT_TYPE, contentType);
        }
    }

    /**
     * Returns the {@link #CONTENT_TYPE} property if not <code>null</code> and
     * a <code>String</code> instance. Otherwise <code>null</code> is
     * returned.
     * @return The content type
     */
    public @Nullable String getContentType() {
        Object value = get(CONTENT_TYPE);
        if (value instanceof String) {
            return (String) value;
        }

        return null;
    }

    /**
     * Sets the {@link #CONTENT_LENGTH} property to <code>contentType</code>
     * if not <code>null</code>.
     * @param contentLength The content length
     */
    public void setContentLength(long contentLength) {
        if (contentLength > 0) {
            put(CONTENT_LENGTH, contentLength);
        }
    }

    /**
     * Returns the {@link #CONTENT_LENGTH} property if not <code>null</code>
     * and a <code>long</code>. Otherwise <code>-1</code> is returned.
     * @return The content length
     */
    public long getContentLength() {
        Object value = get(CONTENT_LENGTH);
        if (value instanceof Long) {
            return (Long) value;
        }

        return -1;
    }

    /**
     * Sets the {@link #CREATION_TIME} property to <code>creationTime</code>
     * if not negative.
     * @param creationTime The creation time
     */
    public void setCreationTime(long creationTime) {
        if (creationTime >= 0) {
            put(CREATION_TIME, creationTime);
        }
    }

    /**
     * Returns the {@link #CREATION_TIME} property if not <code>null</code>
     * and a <code>long</code>. Otherwise <code>-1</code> is returned.
     * @return The creation time
     */
    public long getCreationTime() {
        Object value = get(CREATION_TIME);
        if (value instanceof Long) {
            return (Long) value;
        }

        return -1;
    }

    /**
     * Sets the {@link #MODIFICATION_TIME} property to
     * <code>modificationTime</code> if not negative.
     * @param modificationTime The modification time
     */
    public void setModificationTime(long modificationTime) {
        if (modificationTime >= 0) {
            put(MODIFICATION_TIME, modificationTime);
        }
    }

    /**
     * Returns the {@link #MODIFICATION_TIME} property if not <code>null</code>
     * and a <code>long</code>. Otherwise <code>-1</code> is returned.
     * @return The modification time
     */
    public long getModificationTime() {
        Object value = get(MODIFICATION_TIME);
        if (value instanceof Long) {
            return (Long) value;
        }

        return -1;
    }

    /**
     * Sets the {@link #RESOLUTION_PATH} property to <code>resolutionPath</code>
     * if not <code>null</code>.
     * @param resolutionPath The resolution path
     */
    public void setResolutionPath(String resolutionPath) {
        if (resolutionPath != null) {
            put(RESOLUTION_PATH, resolutionPath);
        }
    }

    /**
     * Returns the {@link #RESOLUTION_PATH} property if not <code>null</code>
     * and a <code>String</code> instance. Otherwise <code>null</code> is
     * returned.
     * @return The resolution path
     */
    public @Nullable String getResolutionPath() {
        Object value = get(RESOLUTION_PATH);
        if (value instanceof String) {
            return (String) value;
        }

        return null;
    }

    /**
     * Sets the {@link #RESOLUTION_PATH_INFO} property to
     * <code>resolutionPathInfo</code> if not <code>null</code>.
     * @param resolutionPathInfo The resolution path info
     */
    public void setResolutionPathInfo(String resolutionPathInfo) {
        if (resolutionPathInfo != null) {
            put(RESOLUTION_PATH_INFO, resolutionPathInfo);
        }
    }

    /**
     * Returns the {@link #RESOLUTION_PATH_INFO} property if not
     * <code>null</code> and a <code>String</code> instance. Otherwise
     * <code>null</code> is returned.
     * @return The resolution path info
     */
    public @Nullable String getResolutionPathInfo() {
        Object value = get(RESOLUTION_PATH_INFO);
        if (value instanceof String) {
            return (String) value;
        }

        return null;
    }

    /**
     * Sets the {@link #PARAMETER_MAP} property to
     * <code>parameterMap</code> if not <code>null</code>.
     * @param parameterMap The parameter map
     */
    public void setParameterMap(Map<String, String> parameterMap) {
        if (parameterMap != null) {
            if (parameterMap.isEmpty()) {
                put(PARAMETER_MAP, Collections.emptyMap());
            } else {
                put(PARAMETER_MAP, new LinkedHashMap<String, String>(parameterMap));
            }
        }
    }

    /**
     * Returns the {@link #PARAMETER_MAP} property if not
     * <code>null</code> and a <code>Map</code> instance. Otherwise
     * <code>null</code> is returned.
     * @return The parameter map
     */
    @SuppressWarnings("unchecked")
    public @Nullable Map<String, String> getParameterMap() {
        Object value = get(PARAMETER_MAP);
        if (value instanceof Map) {
            return (Map<String, String>) value;
        }

        return null;
    }


    /**
     * Make this object read-only. All method calls trying to modify this object
     * result in an exception!
     * @since 2.3 (Sling API Bundle 2.4.0)
     */
    public void lock() {
        this.isReadOnly = true;
    }

    /**
     * Check if this object is read only and if so throw an unsupported operation exception.
     */
    private void checkReadOnly() {
        if ( this.isReadOnly ) {
            throw new UnsupportedOperationException(getClass().getSimpleName() + " is locked");
        }
    }

    @Override
    public void clear() {
        this.checkReadOnly();
        super.clear();
    }

    @Override
    public Object put(@NotNull final String key, final Object value) {
        this.checkReadOnly();
        return super.put(key, value);
    }

    @Override
    public void putAll(@NotNull final Map<? extends String, ? extends Object> m) {
        this.checkReadOnly();
        super.putAll(m);
    }

    @Override
    public Object remove(@NotNull final Object key) {
        this.checkReadOnly();
        return super.remove(key);
    }

    protected void internalPut(@NotNull String key, Object value) {
        super.put(key, value);
    }

    @Override
    public Object clone() {
        ResourceMetadata result = (ResourceMetadata) super.clone();
        result.lockedEntrySet = null;
        result.lockedKeySet = null;
        result.lockedValues = null;
        return result;
    }

	// volatile for correct double-checked locking in getLockedData()
    private transient volatile Set<Map.Entry<String, Object>> lockedEntrySet;
    private transient Set<String> lockedKeySet;
    private transient Collection<Object> lockedValues;

    private void getLockedData() {
        if(isReadOnly && lockedEntrySet == null) {
            synchronized (this) {
                if(isReadOnly && lockedEntrySet == null) {
                    lockedEntrySet = Collections.unmodifiableSet(super.entrySet());
                    lockedKeySet = Collections.unmodifiableSet(super.keySet());
                    lockedValues = Collections.unmodifiableCollection(super.values());
                }
            }
        }
    }

    @Override
    public @NotNull Set<Map.Entry<String, Object>> entrySet() {
        getLockedData();
        return lockedEntrySet != null ? lockedEntrySet : super.entrySet();
    }

    @Override
    public @NotNull Set<String> keySet() {
        getLockedData();
        return lockedKeySet != null ? lockedKeySet : super.keySet();
    }

    @Override
    public @NotNull Collection<Object> values() {
        getLockedData();
        return lockedValues != null ? lockedValues : super.values();
    }
}
