/*
 * 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.jackrabbit.oak.plugins.index.property;

import static com.google.common.base.Preconditions.checkState;
import static org.apache.jackrabbit.oak.plugins.index.IndexConstants.INDEX_CONTENT_NODE_NAME;
import static org.apache.jackrabbit.oak.plugins.index.IndexConstants.INDEX_DEFINITIONS_NAME;
import static org.apache.jackrabbit.oak.plugins.index.IndexConstants.TYPE_PROPERTY_NAME;

import org.apache.jackrabbit.oak.api.PropertyState;
import org.apache.jackrabbit.oak.api.Type;
import org.apache.jackrabbit.oak.commons.PathUtils;
import org.apache.jackrabbit.oak.plugins.index.IndexConstants;
import org.apache.jackrabbit.oak.spi.mount.MountInfoProvider;
import org.apache.jackrabbit.oak.spi.query.Cursor;
import org.apache.jackrabbit.oak.spi.query.Filter;
import org.apache.jackrabbit.oak.spi.query.Filter.PropertyRestriction;
import org.apache.jackrabbit.oak.spi.query.QueryIndex;
import org.apache.jackrabbit.oak.spi.state.ChildNodeEntry;
import org.apache.jackrabbit.oak.spi.state.NodeState;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.common.collect.Iterables;

/**
 * Provides a QueryIndex that does lookups against a property index
 *
 * <p>
 * To define a property index on a subtree you have to add an <code>oak:index</code> node.
 * <br>
 * Next (as a child node) follows the index definition node that:
 * <ul>
 * <li>must be of type <code>oak:QueryIndexDefinition</code></li>
 * <li>must have the <code>type</code> property set to <b><code>property</code></b></li>
 * <li>contains the <code>propertyNames</code> property that indicates what property will be stored in the index</li>
 * </ul>
 * </p>
 * <p>
 * Optionally you can specify
 * <ul> 
 * <li> a uniqueness constraint on a property index by setting the <code>unique</code> flag to <code>true</code></li>
 * <li> that the property index only applies to a certain node type by setting the <code>declaringNodeTypes</code> property</li>
 * </ul>
 * </p>
 * <p>
 * Notes:
 * <ul>
 * <li> <code>propertyNames</code> can be a list of properties, and it is optional.in case it is missing, the node name will be used as a property name reference value</li>
 * <li> <code>reindex</code> is a property that when set to <code>true</code>, triggers a full content reindex.</li>
 * </ul>
 * </p>
 * 
 * <pre>
 * <code>
 * {
 *     NodeBuilder index = root.child("oak:index");
 *     index.child("uuid")
 *         .setProperty("jcr:primaryType", "oak:QueryIndexDefinition", Type.NAME)
 *         .setProperty("type", "property")
 *         .setProperty("propertyNames", "jcr:uuid")
 *         .setProperty("declaringNodeTypes", "mix:referenceable")
 *         .setProperty("unique", true)
 *         .setProperty("reindex", true);
 * }
 * </code>
 * </pre>
 * 
 * @see QueryIndex
 * @see PropertyIndexLookup
 */
class PropertyIndex implements QueryIndex {

    private static final String PROPERTY = "property";

    private static final Logger LOG = LoggerFactory.getLogger(PropertyIndex.class);

    private final MountInfoProvider mountInfoProvider;

    /**
     * Cached property index plan
     */
    private PropertyIndexPlan cachedPlan;

    PropertyIndex(MountInfoProvider mountInfoProvider) {
        this.mountInfoProvider = mountInfoProvider;
    }

    private PropertyIndexPlan getPlan(NodeState root, Filter filter) {
        // Reuse cached plan if the filter is the same (which should always be the case). The filter is compared as a
        // string because it would not be possible to use its equals method since the preparing flag would be different
        // and creating a separate isSimilar method is not worth the effort since it would not be used anymore once the
        // PropertyIndex has been refactored to an AdvancedQueryIndex (which will make the plan cache obsolete).
        PropertyIndexPlan plan = this.cachedPlan;
        if (plan != null && plan.getFilter().toString().equals(filter.toString())) {
            return plan;
        } else {
            plan = createPlan(root, filter, mountInfoProvider);
            this.cachedPlan = plan;
            return plan;
        }
    }

    private static PropertyIndexPlan createPlan(NodeState root, Filter filter,
                                                MountInfoProvider mountInfoProvider) {
        PropertyIndexPlan bestPlan = null;

        // TODO support indexes on a path
        // currently, only indexes on the root node are supported
        NodeState state = root.getChildNode(INDEX_DEFINITIONS_NAME);
        for (ChildNodeEntry entry : state.getChildNodeEntries()) {
            NodeState definition = entry.getNodeState();
            if (wrongIndex(entry, filter, root)) {
                continue;
            }
            if (PROPERTY.equals(definition.getString(TYPE_PROPERTY_NAME))
                    && definition.hasChildNode(INDEX_CONTENT_NODE_NAME)) {
                PropertyIndexPlan plan = new PropertyIndexPlan(
                        entry.getName(), root, definition, filter, mountInfoProvider);
                if (plan.getCost() != Double.POSITIVE_INFINITY) {
                    LOG.debug("property cost for {} is {}",
                            plan.getName(), plan.getCost());
                    if (bestPlan == null || plan.getCost() < bestPlan.getCost()) {
                        bestPlan = plan;
                        // Stop comparing if the costs are the minimum
                        if (plan.getCost() == PropertyIndexPlan.COST_OVERHEAD) {
                            break;
                        }
                    }
                }
            }
        }

        return bestPlan;
    }
    
    private static boolean wrongIndex(ChildNodeEntry entry, Filter filter, NodeState root) {
        // REMARK: similar code is used in oak-lucene, IndexPlanner
        // skip index if "option(index ...)" doesn't match
        NodeState definition = entry.getNodeState();
        if (!isEnabled(definition, root)) {
            return true;
        }
        PropertyRestriction indexName = filter.getPropertyRestriction(IndexConstants.INDEX_NAME_OPTION);
        boolean wrong = false;
        if (indexName != null && indexName.first != null) {
            String name = indexName.first.getValue(Type.STRING);
            String thisName = entry.getName();
            if (thisName.equals(name)) {
                // index name specified, and matches
                return false;
            }
            wrong = true;
        }
        PropertyRestriction indexTag = filter.getPropertyRestriction(IndexConstants.INDEX_TAG_OPTION);
        if (indexTag != null && indexTag.first != null) {
            // index tag specified
            String[] tags = getOptionalStrings(definition, IndexConstants.INDEX_TAGS);
            if (tags == null) {
                // no tag
                return true;
            }
            String tag = indexTag.first.getValue(Type.STRING);
            for(String t : tags) {
                if (t.equals(tag)) {
                    // tag matches
                    return false;
                }
            }
            // no tag matches
            return true;
        }
        // no tag specified
        return wrong;
    }
    
    private static boolean isEnabled(NodeState definition, NodeState root) {
        String useIfExists = definition.getString(IndexConstants.USE_IF_EXISTS);
        if (useIfExists == null) {
            return true;
        }
        if (!PathUtils.isValid(useIfExists)) {
            return false;
        }
        NodeState nodeState = root;
        for (String element : PathUtils.elements(useIfExists)) {
            if (element.startsWith("@")) {
                return nodeState.hasProperty(element.substring(1));
            }
            nodeState = nodeState.getChildNode(element);
            if (!nodeState.exists()) {
                return false;
            }
        }
        return true;
    }
    
    private static String[] getOptionalStrings(NodeState defn, String propertyName) {
        PropertyState ps = defn.getProperty(propertyName);
        if (ps != null) {
            return Iterables.toArray(ps.getValue(Type.STRINGS), String.class);
        }
        return null;
    }

    //--------------------------------------------------------< QueryIndex >--

    @Override
    public double getMinimumCost() {
        return PropertyIndexPlan.COST_OVERHEAD;
    }

    @Override
    public String getIndexName() {
        return PROPERTY;
    }

    @Override
    public double getCost(Filter filter, NodeState root) {
        if (filter.getFullTextConstraint() != null) {
            // not an appropriate index for full-text search
            return Double.POSITIVE_INFINITY;
        }
        if (filter.containsNativeConstraint()) {
            // not an appropriate index for native search
            return Double.POSITIVE_INFINITY;
        }
        if (filter.getPropertyRestrictions().isEmpty()) {
            // not an appropriate index for no property restrictions & selector constraints
            return Double.POSITIVE_INFINITY;
        }
        PropertyIndexPlan plan = getPlan(root, filter);
        if (plan != null) {
            return plan.getCost();
        } else {
            return Double.POSITIVE_INFINITY;
        }
    }

    @Override
    public Cursor query(Filter filter, NodeState root) {
        PropertyIndexPlan plan = getPlan(root, filter);
        checkState(plan != null,
                "Property index is used even when no index"
                + " is available for filter " + filter);
        return plan.execute();
    }

    @Override
    public String getPlan(Filter filter, NodeState root) {
        PropertyIndexPlan plan = getPlan(root, filter);
        if (plan != null) {
            return plan.toString();
        } else {
            return "property index not applicable";
        }
    }

}