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

import java.io.InputStream;
import java.lang.reflect.Array;
import java.math.BigDecimal;
import java.util.Calendar;
import java.util.StringTokenizer;

import javax.jcr.Node;
import javax.jcr.Property;
import javax.jcr.PropertyType;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import javax.jcr.Value;
import javax.jcr.ValueFactory;
import javax.jcr.query.Query;
import javax.jcr.query.QueryManager;
import javax.jcr.query.QueryResult;

import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.resource.ResourceResolver;
import org.apache.sling.api.resource.ResourceUtil;
import org.apache.sling.jcr.resource.internal.helper.LazyInputStream;
import org.slf4j.LoggerFactory;

/**
 * The <code>JcrResourceUtil</code> class provides helper methods used
 * throughout this bundle.
 *
 * @deprecated Use the Resource API instead.
 */
@Deprecated
public class JcrResourceUtil {

    private static volatile boolean LOG_DEPRECATED_QUERY = true;
    private static volatile boolean LOG_DEPRECATED_TO_JAVA_OBJECT_1 = true;
    private static volatile boolean LOG_DEPRECATED_TO_JAVA_OBJECT_2 = true;
    private static volatile boolean LOG_DEPRECATED_CREATE_VALUE = true;
    private static volatile boolean LOG_DEPRECATED_SET_PROPERTY = true;
    private static volatile boolean LOG_DEPRECATED_CREATE_PATH_1 = true;
    private static volatile boolean LOG_DEPRECATED_CREATE_PATH_2 = true;
    private static volatile boolean LOG_DEPRECATED_GET_RST_1 = true;
    private static volatile boolean LOG_DEPRECATED_GET_RST_2 = true;
    private static volatile boolean LOG_DEPRECATED_RT_TO_PATH = true;

    /**
     * Helper method to execute a JCR query.
     *
     * @param session the session
     * @param query the query
     * @param language the language
     * @return the query's result
     * @throws RepositoryException if the {@link QueryManager} cannot be retrieved
     */
    public static QueryResult query(Session session, String query,
            String language) throws RepositoryException {
        if ( LOG_DEPRECATED_QUERY ) {
            LOG_DEPRECATED_QUERY = false;
            LoggerFactory.getLogger(JcrResourceUtil.class).warn("DEPRECATION WARNING: JcrResourceUtil.query is deprecated. Please use the resource resolver.");
        }
        QueryManager qManager = session.getWorkspace().getQueryManager();
        Query q = qManager.createQuery(query, language);
        return q.execute();
    }

    /**
     * Converts a JCR Value to a corresponding Java Object
     *
     * @param value the JCR Value to convert
     * @return the Java Object
     * @throws RepositoryException if the value cannot be converted
     */
    public static Object toJavaObject(Value value) throws RepositoryException {
        if ( LOG_DEPRECATED_TO_JAVA_OBJECT_1 ) {
            LOG_DEPRECATED_TO_JAVA_OBJECT_1 = false;
            LoggerFactory.getLogger(JcrResourceUtil.class).warn("DEPRECATION WARNING: JcrResourceUtil.toJavaObject(Value) is deprecated. Please use the resource resolver API.");
        }
        switch (value.getType()) {
            case PropertyType.DECIMAL:
                return value.getDecimal();
            case PropertyType.BINARY:
                return new LazyInputStream(value);
            case PropertyType.BOOLEAN:
                return value.getBoolean();
            case PropertyType.DATE:
                return value.getDate();
            case PropertyType.DOUBLE:
                return value.getDouble();
            case PropertyType.LONG:
                return value.getLong();
            case PropertyType.NAME: // fall through
            case PropertyType.PATH: // fall through
            case PropertyType.REFERENCE: // fall through
            case PropertyType.STRING: // fall through
            case PropertyType.UNDEFINED: // not actually expected
            default: // not actually expected
                return value.getString();
        }
    }

    /**
     * Converts the value(s) of a JCR Property to a corresponding Java Object.
     * If the property has multiple values the result is an array of Java
     * Objects representing the converted values of the property.
     *
     * @param property the property to be converted to the corresponding Java Object
     * @throws RepositoryException if the conversion cannot take place
     * @return the Object resulting from the conversion
     */
    public static Object toJavaObject(Property property)
            throws RepositoryException {
        if ( LOG_DEPRECATED_TO_JAVA_OBJECT_2 ) {
            LOG_DEPRECATED_TO_JAVA_OBJECT_2 = false;
            LoggerFactory.getLogger(JcrResourceUtil.class).warn("DEPRECATION WARNING: JcrResourceUtil.toJavaObject(Property) is deprecated. Please use the resource resolver API.");
        }
        // multi-value property: return an array of values
        if (property.isMultiple()) {
            Value[] values = property.getValues();
            final Object firstValue = values.length > 0 ? toJavaObject(values[0]) : null;
            final Object[] result;
            if ( firstValue instanceof Boolean ) {
                result = new Boolean[values.length];
            } else if ( firstValue instanceof Calendar ) {
                result = new Calendar[values.length];
            } else if ( firstValue instanceof Double ) {
                result = new Double[values.length];
            } else if ( firstValue instanceof Long ) {
                result = new Long[values.length];
            } else if ( firstValue instanceof BigDecimal) {
                result = new BigDecimal[values.length];
            } else if ( firstValue instanceof InputStream) {
                result = new Object[values.length];
            } else {
                result = new String[values.length];
            }
            for (int i = 0; i < values.length; i++) {
                Value value = values[i];
                if (value != null) {
                    result[i] = toJavaObject(value);
                }
            }
            return result;
        }

        // single value property
        return toJavaObject(property.getValue());
    }

    /**
     * Creates a {@link javax.jcr.Value JCR Value} for the given object with
     * the given Session.
     * Selects the the {@link javax.jcr.PropertyType PropertyType} according
     * the instance of the object's Class
     *
     * @param value object
     * @param session to create value for
     * @return the value or null if not convertible to a valid PropertyType
     * @throws RepositoryException in case of error, accessing the Repository
     */
    public static Value createValue(final Object value, final Session session)
    throws RepositoryException {
        if ( LOG_DEPRECATED_CREATE_VALUE ) {
            LOG_DEPRECATED_CREATE_VALUE = false;
            LoggerFactory.getLogger(JcrResourceUtil.class).warn("DEPRECATION WARNING: JcrResourceUtil.createValue is deprecated. Please use the resource resolver API.");
        }
        Value val;
        ValueFactory fac = session.getValueFactory();
        if(value instanceof Calendar) {
            val = fac.createValue((Calendar)value);
        } else if (value instanceof InputStream) {
            val = fac.createValue(fac.createBinary((InputStream)value));
        } else if (value instanceof Node) {
            val = fac.createValue((Node)value);
        } else if (value instanceof BigDecimal) {
            val = fac.createValue((BigDecimal)value);
        } else if (value instanceof Long) {
            val = fac.createValue((Long)value);
        } else if (value instanceof Short) {
            val = fac.createValue((Short)value);
        } else if (value instanceof Integer) {
            val = fac.createValue((Integer)value);
        } else if (value instanceof Number) {
            val = fac.createValue(((Number)value).doubleValue());
        } else if (value instanceof Boolean) {
            val = fac.createValue((Boolean) value);
        } else if ( value instanceof String ) {
            val = fac.createValue((String)value);
        } else {
            val = null;
        }
        return val;
    }

    /**
     * Sets the value of the property.
     * Selects the {@link javax.jcr.PropertyType PropertyType} according
     * to the instance of the object's class.
     * @param node         The node where the property will be set on.
     * @param propertyName The name of the property.
     * @param propertyValue The value for the property.
     * @throws RepositoryException if the property cannot be set
     */
    public static void setProperty(final Node node,
                                   final String propertyName,
                                   final Object propertyValue)
    throws RepositoryException {
        if ( LOG_DEPRECATED_SET_PROPERTY ) {
            LOG_DEPRECATED_SET_PROPERTY = false;
            LoggerFactory.getLogger(JcrResourceUtil.class).warn("DEPRECATION WARNING: JcrResourceUtil.setProperty is deprecated. Please use the resource resolver API.");
        }
        if ( propertyValue == null ) {
            node.setProperty(propertyName, (String)null);
        } else if ( propertyValue.getClass().isArray() ) {
            final int length = Array.getLength(propertyValue);
            final Value[] setValues = new Value[length];
            for(int i=0; i<length; i++) {
                final Object value = Array.get(propertyValue, i);
                setValues[i] = createValue(value, node.getSession());
            }
            node.setProperty(propertyName, setValues);
        } else {
            node.setProperty(propertyName, createValue(propertyValue, node.getSession()));
        }
    }

    /**
     * Helper method, which returns the given resource type as returned from the
     * {@link org.apache.sling.api.resource.Resource#getResourceType()} as a
     * relative path.
     *
     * @param type The resource type to be converted into a path
     * @return The resource type as a path.
     * @deprecated Use {@link ResourceUtil#resourceTypeToPath(String)}
     */
    @Deprecated
    public static String resourceTypeToPath(String type) {
        if ( LOG_DEPRECATED_RT_TO_PATH ) {
            LOG_DEPRECATED_RT_TO_PATH = false;
            LoggerFactory.getLogger(JcrResourceUtil.class).warn("DEPRECATION WARNING: JcrResourceUtil.resourceTypeToPath is deprecated. Please use the resource resolver API.");
        }
        return type.replaceAll("\\:", "/");
    }

    /**
     * Returns the super type of the given resource type. This is the result of
     * adapting the child resource
     * {@link JcrResourceConstants#SLING_RESOURCE_SUPER_TYPE_PROPERTY} of the
     * <code>Resource</code> addressed by the <code>resourceType</code> to a
     * string. If no such child resource exists or if the resource does not
     * adapt to a string, this method returns <code>null</code>.
     *
     * @param resourceResolver The <code>ResourceResolver</code> used to
     *            access the resource whose path (relative or absolute) is given
     *            by the <code>resourceType</code> parameter.
     * @param resourceType The resource type whose super type is to be returned.
     *            This type is turned into a path by calling the
     *            {@link #resourceTypeToPath(String)} method before trying to
     *            get the resource through the <code>resourceResolver</code>.
     * @return the super type of the <code>resourceType</code> or
     *         <code>null</code> if the resource type does not have a child
     *         resource
     *         {@link JcrResourceConstants#SLING_RESOURCE_SUPER_TYPE_PROPERTY}
     *         adapting to a string.
     * @deprecated Use {@link ResourceUtil#getResourceSuperType(ResourceResolver, String)}
     */
    @SuppressWarnings("deprecation")
    @Deprecated
    public static String getResourceSuperType(
            ResourceResolver resourceResolver, String resourceType) {
        if ( LOG_DEPRECATED_GET_RST_1) {
            LOG_DEPRECATED_GET_RST_1 = false;
            LoggerFactory.getLogger(JcrResourceUtil.class).warn("DEPRECATION WARNING: JcrResourceUtil.getResourceSuperType(String) is deprecated. Please use the resource resolver API.");
        }
        return ResourceUtil.getResourceSuperType(resourceResolver, resourceType);
    }

    /**
     * Returns the resource super type of the given resource. This is either the
     * child resource
     * {@link JcrResourceConstants#SLING_RESOURCE_SUPER_TYPE_PROPERTY} if the
     * given <code>resource</code> adapted to a string or the result of
     * calling the {@link #getResourceSuperType(ResourceResolver, String)}
     * method on the resource type of the <code>resource</code>.
     * <p>
     * This mechanism allows to specifically set the resource super type on a
     * per-resource level overwriting any resource super type hierarchy
     * pre-defined by the actual resource type of the resource.
     *
     * @param resource The <code>Resource</code> whose resource super type is
     *            requested.
     * @return The resource super type or <code>null</code> if the algorithm
     *         described above does not yield a resource super type.
     * @deprecated Call {@link ResourceUtil#findResourceSuperType(Resource)}
     */
    @SuppressWarnings("deprecation")
    @Deprecated
    public static String getResourceSuperType(Resource resource) {
        if ( LOG_DEPRECATED_GET_RST_2) {
            LOG_DEPRECATED_GET_RST_2 = false;
            LoggerFactory.getLogger(JcrResourceUtil.class).warn("DEPRECATION WARNING: JcrResourceUtil.getResourceSuperType(Resource) is deprecated. Please use the resource resolver API.");
        }
        String resourceSuperType = resource.getResourceSuperType();
        if ( resourceSuperType == null ) {
            final ResourceResolver resolver = resource.getResourceResolver();

            // try explicit resourceSuperType resource
            final String resourceType = resource.getResourceType();
            resourceSuperType = ResourceUtil.getResourceSuperType(resolver, resourceType);
        }

        return resourceSuperType;
    }

    /**
     * Creates or gets the {@link javax.jcr.Node Node} at the given Path.
     * In case it has to create the Node all non-existent intermediate path-elements
     * will be create with the given intermediate node type and the returned node
     * will be created with the given nodeType
     *
     * @param path to create
     * @param intermediateNodeType to use for creation of intermediate nodes (or null)
     * @param nodeType to use for creation of the final node (or null)
     * @param session to use
     * @param autoSave Should save be called when a new node is created?
     * @return the Node at path
     * @throws RepositoryException in case of exception accessing the Repository
     */
    public static Node createPath(String path,
                                  String intermediateNodeType,
                                  String nodeType,
                                  Session session,
                                  boolean autoSave)
            throws RepositoryException {
        if ( LOG_DEPRECATED_CREATE_PATH_1 ) {
            LOG_DEPRECATED_CREATE_PATH_1 = false;
            LoggerFactory.getLogger(JcrResourceUtil.class).warn("DEPRECATION WARNING: JcrResourceUtil.createPath(String, ...) is deprecated. Please use the resource resolver API.");
        }
        if (path == null || path.length() == 0 || "/".equals(path)) {
            return session.getRootNode();
        }
        // sanitize path if it ends with a slash
        if ( path.endsWith("/") ) {
            path = path.substring(0, path.length() - 1);
        }

        if (!session.itemExists(path)) {
            String existingPath = findExistingPath(path, session);


            String relativePath = null;
            Node parentNode = null;
            if (existingPath != null) {
                parentNode = session.getNode(existingPath);
                relativePath = path.substring(existingPath.length() + 1);
            } else {
                relativePath = path.substring(1);
                parentNode = session.getRootNode();
            }

            return createPath(parentNode,
                    relativePath,
                    intermediateNodeType,
                    nodeType,
                    autoSave);
        } else {
            return session.getNode(path);
        }
    }

    /**
     * Creates or gets the {@link javax.jcr.Node Node} at the given Path.
     * In case it has to create the Node all non-existent intermediate path-elements
     * will be create with the given intermediate node type and the returned node
     * will be created with the given nodeType
     *
     * @param parentNode starting node
     * @param relativePath to create
     * @param intermediateNodeType to use for creation of intermediate nodes (or null)
     * @param nodeType to use for creation of the final node (or null)
     * @param autoSave Should save be called when a new node is created?
     * @return the Node at path
     * @throws RepositoryException in case of exception accessing the Repository
     */
    public static Node createPath(Node   parentNode,
                                  String relativePath,
                                  String intermediateNodeType,
                                  String nodeType,
                                  boolean autoSave)
    throws RepositoryException {
        if ( LOG_DEPRECATED_CREATE_PATH_2 ) {
            LOG_DEPRECATED_CREATE_PATH_2 = false;
            LoggerFactory.getLogger(JcrResourceUtil.class).warn("DEPRECATION WARNING: JcrResourceUtil.createPath(Node,...) is deprecated. Please use the resource resolver API.");
        }
        if (relativePath == null || relativePath.length() == 0 || "/".equals(relativePath)) {
            return parentNode;
        }
        // sanitize path if it ends with a slash
        if ( relativePath.endsWith("/") ) {
            relativePath = relativePath.substring(0, relativePath.length() - 1);
        }

        if (!parentNode.hasNode(relativePath)) {
            Session session = parentNode.getSession();
            String path = parentNode.getPath() + "/" + relativePath;
            String existingPath = findExistingPath(path, session);

            if (existingPath != null) {
                parentNode = session.getNode(existingPath);
                relativePath = path.substring(existingPath.length() + 1);
            }

            Node node = parentNode;
            int pos = relativePath.lastIndexOf('/');
            if ( pos != -1 ) {
                final StringTokenizer st = new StringTokenizer(relativePath.substring(0, pos), "/");
                while ( st.hasMoreTokens() ) {
                    final String token = st.nextToken();
                    if ( !node.hasNode(token) ) {
                        try {
                            if ( intermediateNodeType != null ) {
                                node.addNode(token, intermediateNodeType);
                            } else {
                                node.addNode(token);
                            }
                            if ( autoSave ) session.save();
                        } catch (RepositoryException re) {
                            // we ignore this as this folder might be created from a different task
                            session.refresh(false);
                        }
                    }
                    node = node.getNode(token);
                }
                relativePath = relativePath.substring(pos + 1);
            }
            if ( !node.hasNode(relativePath) ) {
                if ( nodeType != null ) {
                    node.addNode(relativePath, nodeType);
                } else {
                    node.addNode(relativePath);
                }
                if ( autoSave ) session.save();
            }
            return node.getNode(relativePath);
        } else {
            return parentNode.getNode(relativePath);
        }
    }

    private static String findExistingPath(String path, Session session)
            throws RepositoryException {
        //find the parent that exists
        // we can start from the youngest child in tree
        int currentIndex = path.lastIndexOf('/');
        String temp = path;
        String existingPath = null;
        while (currentIndex > 0) {
            temp = temp.substring(0, currentIndex);
            //break when first existing parent is found
            if (session.itemExists(temp)) {
                existingPath = temp;
                break;
            }
            currentIndex = temp.lastIndexOf("/");
        }

        return existingPath;
    }
}
