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

import java.util.List;
import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger;

import javax.jcr.PropertyType;
import javax.jcr.Repository;

import org.apache.commons.io.IOUtils;
import org.apache.jackrabbit.JcrConstants;
import org.apache.jackrabbit.api.JackrabbitRepository;
import org.apache.jackrabbit.oak.api.Blob;
import org.apache.jackrabbit.oak.api.CommitFailedException;
import org.apache.jackrabbit.oak.api.PropertyState;
import org.apache.jackrabbit.oak.api.Root;
import org.apache.jackrabbit.oak.api.Tree;
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.plugins.index.search.FulltextIndexConstants.IndexingMode;
import org.apache.jackrabbit.oak.plugins.index.search.util.IndexHelper;
import org.apache.jackrabbit.oak.plugins.memory.MemoryNodeStore;
import org.apache.jackrabbit.oak.plugins.memory.ModifiedNodeState;
import org.apache.jackrabbit.oak.plugins.name.NamespaceEditorProvider;
import org.apache.jackrabbit.oak.plugins.nodetype.TypeEditorProvider;
import org.apache.jackrabbit.oak.plugins.nodetype.write.NodeTypeRegistry;
import org.apache.jackrabbit.oak.plugins.tree.factories.RootFactory;
import org.apache.jackrabbit.oak.spi.commit.CommitInfo;
import org.apache.jackrabbit.oak.spi.commit.CompositeEditorProvider;
import org.apache.jackrabbit.oak.spi.commit.Editor;
import org.apache.jackrabbit.oak.spi.commit.EditorHook;
import org.apache.jackrabbit.oak.spi.commit.EditorProvider;
import org.apache.jackrabbit.oak.spi.state.ApplyDiff;
import org.apache.jackrabbit.oak.spi.state.NodeBuilder;
import org.apache.jackrabbit.oak.spi.state.NodeState;
import org.apache.jackrabbit.oak.spi.state.NodeStore;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.collect.ImmutableSet.of;
import static org.apache.jackrabbit.JcrConstants.JCR_CONTENT;
import static org.apache.jackrabbit.oak.api.Type.STRINGS;
import static org.apache.jackrabbit.oak.plugins.index.IndexConstants.INDEX_DEFINITIONS_NAME;
import static org.apache.jackrabbit.oak.plugins.index.IndexConstants.INDEX_DEFINITIONS_NODE_TYPE;
import static org.apache.jackrabbit.oak.plugins.index.IndexConstants.REINDEX_PROPERTY_NAME;
import static org.apache.jackrabbit.oak.plugins.index.IndexConstants.TYPE_PROPERTY_NAME;
import static org.apache.jackrabbit.oak.plugins.memory.PropertyStates.createProperty;

public class TestUtil {
    private static final AtomicInteger COUNTER = new AtomicInteger();

    public static final String NT_TEST = "oak:TestNode";

    public static final String TEST_NODE_TYPE = "[oak:TestNode]\n" +
            " - * (UNDEFINED) multiple\n" +
            " - * (UNDEFINED)\n" +
            " + * (nt:base) = oak:TestNode VERSION";

    static void useV2(NodeBuilder idxNb) {
        if (!IndexFormatVersion.getDefault().isAtLeast(IndexFormatVersion.V2)) {
            idxNb.setProperty(FulltextIndexConstants.COMPAT_MODE, IndexFormatVersion.V2.getVersion());
        }
    }

    static void useV2(Tree idxTree) {
        if (!IndexFormatVersion.getDefault().isAtLeast(IndexFormatVersion.V2)) {
            idxTree.setProperty(FulltextIndexConstants.COMPAT_MODE, IndexFormatVersion.V2.getVersion());
        }
    }

    public static NodeBuilder newFTIndexDefinitionV2(
            @NotNull NodeBuilder index, @NotNull String name, String type,
            @Nullable Set<String> propertyTypes) {
        NodeBuilder nb = IndexHelper.newFTIndexDefinition(index, name, type, propertyTypes, null, null, null);
        useV2(nb);
        return nb;
    }

    public static Tree enableForFullText(Tree props, String propName) {
        return enableForFullText(props, propName, false);
    }

    public static Tree enableForFullText(Tree props, String propName,  boolean regex) {
        Tree prop = props.addChild(unique("prop"));
        prop.setProperty(FulltextIndexConstants.PROP_NAME, propName);
        prop.setProperty(FulltextIndexConstants.PROP_PROPERTY_INDEX, true);
        prop.setProperty(FulltextIndexConstants.PROP_IS_REGEX, regex);
        prop.setProperty(FulltextIndexConstants.PROP_NODE_SCOPE_INDEX, true);
        prop.setProperty(FulltextIndexConstants.PROP_ANALYZED, true);
        prop.setProperty(FulltextIndexConstants.PROP_USE_IN_EXCERPT, true);
        prop.setProperty(FulltextIndexConstants.PROP_USE_IN_SPELLCHECK, true);
        return prop;
    }
    
    public static Tree enableForOrdered(Tree props, String propName) {
        Tree prop = enablePropertyIndex(props, propName, false);
        prop.setProperty("ordered", true);
        return prop;
    }

    public static Tree enablePropertyIndex(Tree props, String propName,  boolean regex) {
        Tree prop = props.addChild(unique("prop"));
        prop.setProperty(FulltextIndexConstants.PROP_NAME, propName);
        prop.setProperty(FulltextIndexConstants.PROP_PROPERTY_INDEX, true);
        prop.setProperty(FulltextIndexConstants.PROP_IS_REGEX, regex);
        prop.setProperty(FulltextIndexConstants.PROP_NODE_SCOPE_INDEX, false);
        prop.setProperty(FulltextIndexConstants.PROP_ANALYZED, false);
        return prop;
    }

    public static Tree enableFunctionIndex(Tree props, String function) {
        Tree prop = props.addChild(unique("prop"));
        prop.setProperty(FulltextIndexConstants.PROP_FUNCTION, function);
        return prop;
    }

    public static AggregatorBuilder newNodeAggregator(Tree indexDefn){
        return new AggregatorBuilder(indexDefn);
    }

    public static Tree newRulePropTree(Tree indexDefn, String typeName){
        Tree rules = indexDefn.addChild(FulltextIndexConstants.INDEX_RULES);
        rules.setOrderableChildren(true);
        Tree rule = rules.addChild(typeName);
        Tree props = rule.addChild(FulltextIndexConstants.PROP_NODE);
        props.setOrderableChildren(true);
        return props;
    }

    public static NodeBuilder child(NodeBuilder nb, String path) {
        for (String name : PathUtils.elements(checkNotNull(path))) {
            nb = nb.child(name);
        }
        return nb;
    }

    static class AggregatorBuilder {
        private final Tree aggs;

        private AggregatorBuilder(Tree indexDefn) {
            this.aggs = indexDefn.addChild(FulltextIndexConstants.AGGREGATES);
        }

        AggregatorBuilder newRuleWithName(String primaryType,
                                          List<String> includes){
            Tree agg = aggs.addChild(primaryType);
            for (String include : includes){
                agg.addChild(unique("include")).setProperty(FulltextIndexConstants.AGG_PATH, include);
            }
            return this;
        }
    }

    static String unique(String name){
        return name + COUNTER.getAndIncrement();
    }

    public static NodeBuilder registerTestNodeType(NodeBuilder builder){
        registerNodeType(builder, TEST_NODE_TYPE);
        return builder;
    }

    public static void registerNodeType(NodeBuilder builder, String nodeTypeDefn){
        //Taken from org.apache.jackrabbit.oak.plugins.nodetype.write.InitialContent
        NodeState base = ModifiedNodeState.squeeze(builder.getNodeState());
        NodeStore store = new MemoryNodeStore(base);
        Root root = RootFactory.createSystemRoot(
                store, new EditorHook(new CompositeEditorProvider(
                        new NamespaceEditorProvider(),
                        new TypeEditorProvider())), null, null, null);
        NodeTypeRegistry.register(root, IOUtils.toInputStream(nodeTypeDefn), "test node types");
        NodeState target = store.getRoot();
        target.compareAgainstBaseState(base, new ApplyDiff(builder));
    }

    public static Tree createNodeWithType(Tree t, String nodeName, String typeName){
        t = t.addChild(nodeName);
        t.setProperty(JcrConstants.JCR_PRIMARYTYPE, typeName, Type.NAME);
        return t;
    }

    public static NodeBuilder createNodeWithType(NodeBuilder builder, String nodeName, String typeName){
        builder = builder.child(nodeName);
        builder.setProperty(JcrConstants.JCR_PRIMARYTYPE, typeName, Type.NAME);
        return builder;
    }

    public static Tree createFileNode(Tree tree, String name, Blob content, String mimeType){
        Tree fileNode = tree.addChild(name);
        fileNode.setProperty(JcrConstants.JCR_PRIMARYTYPE, JcrConstants.NT_FILE, Type.NAME);
        Tree jcrContent = fileNode.addChild(JCR_CONTENT);
        jcrContent.setProperty(JcrConstants.JCR_DATA, content);
        jcrContent.setProperty(JcrConstants.JCR_MIMETYPE, mimeType);
        return jcrContent;
    }

    public static Tree createFulltextIndex(Tree index, String name, String type) throws CommitFailedException {
        Tree def = index.addChild(INDEX_DEFINITIONS_NAME).addChild(name);
        def.setProperty(JcrConstants.JCR_PRIMARYTYPE,
                INDEX_DEFINITIONS_NODE_TYPE, Type.NAME);
        def.setProperty(TYPE_PROPERTY_NAME, type);
        def.setProperty(REINDEX_PROPERTY_NAME, true);
        def.setProperty(createProperty(FulltextIndexConstants.INCLUDE_PROPERTY_TYPES,
                of(PropertyType.TYPENAME_STRING, PropertyType.TYPENAME_BINARY), STRINGS));
        return index.getChild(INDEX_DEFINITIONS_NAME).getChild(name);
    }

    public static void shutdown(Repository repository) {
        if (repository instanceof JackrabbitRepository) {
            ((JackrabbitRepository) repository).shutdown();
        }
    }

    public static NodeBuilder enableIndexingMode(NodeBuilder builder, IndexingMode indexingMode){
        builder.setProperty(createAsyncProperty(indexingMode));
        return builder;
    }

    public static Tree enableIndexingMode(Tree tree, IndexingMode indexingMode){
        tree.setProperty(createAsyncProperty(indexingMode));
        return tree;
    }

    private static PropertyState createAsyncProperty(String indexingMode) {
        return createProperty(IndexConstants.ASYNC_PROPERTY_NAME, of(indexingMode , "async"), STRINGS);
    }

    private static PropertyState createAsyncProperty(IndexingMode indexingMode) {
        switch(indexingMode) {
            case SYNC :
                return createAsyncProperty(indexingMode.asyncValueName());
            case ASYNC:
                return createProperty(IndexConstants.ASYNC_PROPERTY_NAME, of("async"), STRINGS);
            default:
                throw new IllegalArgumentException("Unknown mode " + indexingMode);
        }
    }

    public static class OptionalEditorProvider implements EditorProvider {
        public EditorProvider delegate;

        @Override
        public Editor getRootEditor(NodeState before, NodeState after, NodeBuilder builder, CommitInfo info) throws CommitFailedException {
            if (delegate != null){
                return delegate.getRootEditor(before, after, builder, info);
            }
            return null;
        }


    }
}
