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

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.index.lucene.FieldFactory.newPathField;
import static org.apache.jackrabbit.oak.plugins.memory.PropertyStates.createProperty;

import java.io.IOException;
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.lucene.util.LuceneIndexHelper;
import org.apache.jackrabbit.oak.plugins.index.search.FulltextIndexConstants;
import org.apache.jackrabbit.oak.plugins.index.search.FulltextIndexConstants.IndexingMode;
import org.apache.jackrabbit.oak.plugins.index.search.IndexFormatVersion;
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.apache.lucene.document.Document;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.IOContext;
import org.apache.lucene.store.IndexOutput;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

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 newLuceneIndexDefinitionV2(
        @NotNull NodeBuilder index, @NotNull String name,
        @Nullable Set<String> propertyTypes) {
        NodeBuilder nb = LuceneIndexHelper.newLuceneIndexDefinition(index, name, 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;
    }

    public static Document newDoc(String path) {
        Document doc = new Document();
        doc.add(newPathField(path));
        return doc;
    }

    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) 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, LuceneIndexConstants.TYPE_LUCENE);
        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;
    }

    public static int createFile(Directory dir, String fileName, String content) throws IOException {
        byte[] data = content.getBytes();
        IndexOutput o = dir.createOutput(fileName, IOContext.DEFAULT);
        o.writeBytes(data, data.length);
        o.close();
        return data.length;
    }

    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 NRT:
            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;
        }

    }
}
