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

import javax.jcr.Item;
import javax.jcr.Node;
import javax.jcr.Property;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import javax.jcr.nodetype.NodeType;
import javax.jcr.version.VersionHistory;
import javax.jcr.version.VersionManager;

import org.apache.commons.lang3.StringUtils;
import org.apache.jackrabbit.api.JackrabbitSession;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.resource.ResourceResolver;
import org.apache.sling.jcr.resource.internal.HelperData;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class JcrItemResourceFactory {

    /** Default logger */
    private static final Logger log = LoggerFactory.getLogger(JcrItemResourceFactory.class);

    private final Session session;

    private final HelperData helper;

    private final boolean isJackrabbit;

    public JcrItemResourceFactory(final Session session, final HelperData helper) {
        this.helper = helper;
        this.session = session;
        this.isJackrabbit = session instanceof JackrabbitSession;
    }

    /**
     * Creates a <code>Resource</code> instance for the item found at the
     * given path. If no item exists at that path or the item does not have
     * read-access for the session of this resolver, <code>null</code> is
     * returned.
     *
     * @param resourcePath The absolute path
     * @return The <code>Resource</code> for the item at the given path.
     * @throws RepositoryException If an error occurrs accessing checking the
     *             item in the repository.
     */
    public JcrItemResource<?> createResource(final ResourceResolver resourceResolver, final String resourcePath,
                                             final Resource parent, final Map<String, String> parameters) throws RepositoryException {
        if (resourcePath == null) {
            log.debug("createResource: {} maps to an empty JCR path", resourcePath);
            return null;
        }

        final String version;
        if (parameters != null && parameters.containsKey("v")) {
            version = parameters.get("v");
        } else {
            version = null;
        }

        Node parentNode = null;
        String parentResourcePath = null;
        if (parent != null) {
            parentNode = parent.adaptTo(Node.class);
            parentResourcePath = parent.getPath();
        }

        Item item;
        if (parentNode != null && resourcePath.startsWith(parentResourcePath)) {
            String subPath = resourcePath.substring(parentResourcePath.length());
            if (!subPath.isEmpty() && subPath.charAt(0) == '/') {
                subPath = subPath.substring(1);
            }
            item = getSubitem(parentNode, subPath);
        } else {
            item = getItemOrNull(resourcePath);
        }

        if (item != null && version != null) {
            item = getHistoricItem(item, version);
        }

        if (item == null) {
            log.debug("createResource: No JCR Item exists at path '{}'", resourcePath);
            return null;
        } else {
            final JcrItemResource<?> resource;
            if (item.isNode()) {
                log.debug("createResource: Found JCR Node Resource at path '{}'", resourcePath);
                resource = new JcrNodeResource(resourceResolver, resourcePath, version, (Node) item, helper);
            } else {
                log.debug("createResource: Found JCR Property Resource at path '{}'", resourcePath);
                resource = new JcrPropertyResource(resourceResolver, resourcePath, version, (Property) item);
            }
            resource.getResourceMetadata().setParameterMap(parameters);
            return resource;
        }
    }

    private Item getHistoricItem(Item item, String versionSpecifier) throws RepositoryException {
        Item currentItem = item;
        LinkedList<String> relPath = new LinkedList<>();
        Node version = null;
        while (!"/".equals(currentItem.getPath())) {
            if (isVersionable(currentItem)) {
                version = getFrozenNode((Node) currentItem, versionSpecifier);
                break;
            } else {
                relPath.addFirst(currentItem.getName());
                currentItem = currentItem.getParent();
            }
        }
        if (version != null) {
            return getSubitem(version, StringUtils.join(relPath.iterator(), '/'));
        }
        return null;
    }

    private static Item getSubitem(Node node, String relPath) {
        try {
            if (relPath.length() == 0) { // not using isEmpty() due to 1.5 compatibility
                return node;
            } else if (node.hasNode(relPath)) {
                return node.getNode(relPath);
            } else if (node.hasProperty(relPath)) {
                return node.getProperty(relPath);
            } else {
                return null;
            }
        } catch (RepositoryException e) {
            log.debug("getSubitem: Can't get subitem {} of {}: {}", relPath, node, e.toString());
            return null;
        }
    }

    private Node getFrozenNode(Node node, String versionSpecifier) throws RepositoryException {
        final VersionManager versionManager = session.getWorkspace().getVersionManager();
        final VersionHistory history = versionManager.getVersionHistory(node.getPath());
        if (history.hasVersionLabel(versionSpecifier)) {
            return history.getVersionByLabel(versionSpecifier).getFrozenNode();
        } else if (history.hasNode(versionSpecifier)) {
            return history.getVersion(versionSpecifier).getFrozenNode();
        } else {
            return null;
        }
    }

    private static boolean isVersionable(Item item) throws RepositoryException {
        return item.isNode() && ((Node) item).isNodeType(NodeType.MIX_VERSIONABLE);
    }

    Item getItemOrNull(String path) {
        // Check first if the path is absolute. If it isn't, then we return null because the previous itemExists method,
        // which was replaced by this method, would have returned null as well (instead of throwing an exception).
        if (path.isEmpty() || path.charAt(0) != '/') {
            return null;
        }

        Item item = null;
        try {
            // Use fast getItemOrNull if session is a JackrabbitSession
            if (this.isJackrabbit) {
                item = ((JackrabbitSession) session).getItemOrNull(path);
            }
            // Fallback to slower itemExists & getItem pattern
            else if (session.itemExists(path)) {
                item = session.getItem(path);
            }
        } catch (RepositoryException e) {
            log.debug("Unable to access item at " + path + ", possibly invalid path", e);
        }

        return item;
    }

    @Nullable Node getParentOrNull(@NotNull Item child, @NotNull String parentPath) {
        Node parent = null;
        try {
            // Use fast getParentOrNull if session is a JackrabbitSession
            if (this.isJackrabbit) {
                parent = ((JackrabbitSession) session).getParentOrNull(child);
            } else if (session.nodeExists(parentPath)) {
                // Fallback to slower nodeExists & getNode pattern
                parent = session.getNode(parentPath);
            }
        } catch (RepositoryException e) {
            log.debug("Unable to access node at {}", parentPath, e);
        }

        return parent;
    }

}
