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

import java.io.InputStream;
import java.net.URI;
import java.security.AccessControlException;
import java.util.Iterator;
import java.util.Map;

import javax.jcr.Item;
import javax.jcr.ItemNotFoundException;
import javax.jcr.Node;
import javax.jcr.Property;
import javax.jcr.RepositoryException;

import org.apache.sling.adapter.annotations.Adaptable;
import org.apache.sling.adapter.annotations.Adapter;
import org.apache.sling.api.resource.ModifiableValueMap;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.resource.ResourceResolver;
import org.apache.sling.api.resource.ValueMap;
import org.apache.sling.api.resource.external.ExternalizableInputStream;
import org.apache.sling.api.resource.external.URIProvider;
import org.apache.sling.jcr.resource.api.JcrResourceConstants;
import org.apache.sling.jcr.resource.internal.HelperData;
import org.apache.sling.jcr.resource.internal.JcrModifiableValueMap;
import org.apache.sling.jcr.resource.internal.JcrValueMap;
import org.apache.sling.jcr.resource.internal.NodeUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/** A Resource that wraps a JCR Node */
@Adaptable(adaptableClass=Resource.class, adapters={
        @Adapter({Node.class, Map.class, Item.class, ValueMap.class}),
        @Adapter(value=InputStream.class, condition="If the resource is a JcrNodeResource and has a jcr:data property or is an nt:file node."),
        @Adapter(value=ExternalizableInputStream.class, condition="If the resource is a JcrNodeResource and has a jcr:data property or is an nt:file node, and can be read using a secure URL.")
})
class JcrNodeResource extends JcrItemResource<Node> { // this should be package private, see SLING-1414

    /** marker value for the resourceSupertType before trying to evaluate */
    private static final String UNSET_RESOURCE_SUPER_TYPE = "<unset>";

    /** default log */
    private static final Logger LOGGER = LoggerFactory.getLogger(JcrNodeResource.class);

    private String resourceType;

    private String resourceSuperType;

    private final HelperData helper;

    /**
     * Constructor
     * @param resourceResolver
     * @param path The path of the resource (lazily initialized if null)
     * @param version
     * @param node The Node underlying this resource
     * @param helper the helper data providing access to the dynamic class loader for loading serialized objects.
     */
    public JcrNodeResource(@NotNull final ResourceResolver resourceResolver,
                           @NotNull final String path,
                           @Nullable final String version,
                           @NotNull final Node node,
                           @NotNull final HelperData helper) {
        super(resourceResolver, path, version, node, new JcrNodeResourceMetadata(node));
        this.helper = helper;
        this.resourceSuperType = UNSET_RESOURCE_SUPER_TYPE;
    }

    /**
     * @see org.apache.sling.api.resource.Resource#getResourceType()
     */
    @Override
    public @NotNull String getResourceType() {
        if ( this.resourceType == null ) {
            try {
                this.resourceType = getResourceTypeForNode(getNode());
            } catch (final RepositoryException e) {
                LOGGER.error("Unable to get resource type for node " + getNode(), e);
                this.resourceType = "<unknown resource type>";
            }
        }
        return resourceType;
    }

    /**
     * @see org.apache.sling.api.resource.Resource#getResourceSuperType()
     */
    @Override
    public @Nullable String getResourceSuperType() {
        // Yes, this isn't how you're supposed to compare Strings, but this is intentional.
        if ( resourceSuperType == UNSET_RESOURCE_SUPER_TYPE ) {
            try {
                if (getNode().hasProperty(JcrResourceConstants.SLING_RESOURCE_SUPER_TYPE_PROPERTY)) {
                    resourceSuperType = getNode().getProperty(JcrResourceConstants.SLING_RESOURCE_SUPER_TYPE_PROPERTY).getValue().getString();
                }
            } catch (RepositoryException re) {
                // we ignore this
            }
            if ( resourceSuperType == UNSET_RESOURCE_SUPER_TYPE ) {
                resourceSuperType = null;
            }
        }
        return resourceSuperType;
    }

    @Override
    @SuppressWarnings("unchecked")
    public <Type> Type adaptTo(Class<Type> type) {
        if (type == Node.class || type == Item.class) {
            return (Type) getNode(); // unchecked cast
        } else if (type == InputStream.class) {
            return (Type) getInputStream(); // unchecked cast
        } else if (type == Map.class || type == ValueMap.class) {
            return (Type) new JcrValueMap(getNode(), this.helper);
        } else if (type == ModifiableValueMap.class ) {
            // check write
            try {
                getNode().getSession().checkPermission(getPath(),
                    "set_property");
                return (Type) new JcrModifiableValueMap(getNode(), this.helper);
            } catch (AccessControlException ace) {
                // the user has no write permission, cannot adapt
                LOGGER.debug(
                    "adaptTo(ModifiableValueMap): Cannot set properties on {}",
                    this);
            } catch (RepositoryException e) {
                // some other problem, cannot adapt
                LOGGER.debug(
                    "adaptTo(ModifiableValueMap): Unexpected problem for {}",
                    this);
            }
        }

        // fall back to default implementation
        return super.adaptTo(type);
    }

    @Override
    public String toString() {
        return getClass().getSimpleName()
        	+ ", type=" + getResourceType()
        	+ ", superType=" + getResourceSuperType()
            + ", path=" + getPath();
    }

    // ---------- internal -----------------------------------------------------

    private @NotNull Node getNode() {
        return getItem();
    }

    /**
     * Returns a stream to the <em>jcr:data</em> property if the
     * {@link #getNode() node} is an <em>nt:file</em> or <em>nt:resource</em>
     * node. Otherwise returns <code>null</code>.
     */
    private @Nullable InputStream getInputStream() {
        // implement this for nt:file only
        final Node node = getNode();
        try {
            Property data;
            try {
                data = NodeUtil.getPrimaryProperty(node);
            } catch (ItemNotFoundException infe) {
                // we don't actually care, but log for completeness
                LOGGER.debug("getInputStream: No primary items for {}", this, infe);
                data = null;
            }

            URI uri = convertToPublicURI();
            if (uri != null && data != null) {
                return new JcrExternalizableInputStream(data, uri);
            }
            if (data != null) {
                return data.getBinary().getStream();
            }

        } catch (RepositoryException re) { 
            LOGGER.error("getInputStream: Cannot get InputStream for {}", this, re);
        }

        // fallback to non-streamable resource
        return null;
    }

    /**
     * Ask each URIProvider in turn for a Public URI, and return the first
     * public URI provided.
     * @return a public URI.
     */
    private @Nullable URI convertToPublicURI() {
        for (URIProvider up : helper.getURIProviders()) {
            try {
                return up.toURI(this, URIProvider.Scope.EXTERNAL, URIProvider.Operation.READ);
            } catch (IllegalArgumentException e) {
                LOGGER.debug("{} declined toURI for resource '{}'", up.getClass(), getPath(), e);
            }
        }
        return null;
    }


    // ---------- Descendable interface ----------------------------------------

    @Override
    @Nullable Iterator<Resource> listJcrChildren() {
        try {
            if (getNode().hasNodes()) {
                return new JcrNodeResourceIterator(getResourceResolver(), path, version,
                    getNode().getNodes(), this.helper, null);
            }
        } catch (final RepositoryException re) {
            LOGGER.error("listChildren: Cannot get children of " + this, re);
        }

        return null;
    }
}
