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

import java.io.IOException;
import java.util.List;
import java.util.Set;

import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import org.apache.jackrabbit.oak.api.CommitFailedException;
import org.apache.jackrabbit.oak.commons.PathUtils;
import org.apache.jackrabbit.oak.plugins.commit.AnnotatingConflictHandler;
import org.apache.jackrabbit.oak.plugins.commit.ConflictHook;
import org.apache.jackrabbit.oak.plugins.commit.ConflictValidatorProvider;
import org.apache.jackrabbit.oak.plugins.document.memory.MemoryDocumentStore;
import org.apache.jackrabbit.oak.plugins.document.util.Utils;
import org.apache.jackrabbit.oak.spi.commit.CommitHook;
import org.apache.jackrabbit.oak.spi.commit.CommitInfo;
import org.apache.jackrabbit.oak.spi.commit.CompositeHook;
import org.apache.jackrabbit.oak.spi.commit.EditorHook;
import org.apache.jackrabbit.oak.spi.commit.EmptyHook;
import org.apache.jackrabbit.oak.spi.state.NodeBuilder;
import org.apache.jackrabbit.oak.spi.state.NodeState;
import org.jetbrains.annotations.NotNull;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import static org.apache.jackrabbit.oak.plugins.document.DocumentMK.UPDATE_LIMIT;
import static org.hamcrest.CoreMatchers.hasItem;
import static org.hamcrest.CoreMatchers.not;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertThat;

public class NodeStoreDiffTest {

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

    @Rule
    public DocumentMKBuilderProvider builderProvider = new DocumentMKBuilderProvider();

    private DocumentNodeStore ns;
    private final TestDocumentStore tds = new TestDocumentStore();

    @Before
    public void setUp() throws IOException {
        ns = builderProvider.newBuilder()
                .setDocumentStore(tds)
                .setUseSimpleRevision(true) //To simplify debugging
                .setAsyncDelay(0)
                .memoryCacheSize(0) //Keep the cache size zero such that nodeCache is not used
                .getNodeStore();
    }

    @Test
    public void diffWithConflict() throws Exception{
        //Last rev on /var would be 1-0-1
        createNodes("/var/a", "/var/b/b1");

        //1. Dummy commits to bump the version no
        createNodes("/fake/b");
        createNodes("/fake/c");

        //Root rev = 3-0-1
        //Root rev = 3-0-1

        //2. Create a node under /var/a but hold on commit
        NodeBuilder b1 = ns.getRoot().builder();
        createNodes(b1, "/var/a/a1");

        //3. Remove a node under /var/b and commit it
        NodeBuilder b2 = ns.getRoot().builder();
        b2.child("var").child("b").child("b1").remove();
        merge(b2);

        //4. Now merge and commit the changes in b1 and include conflict hooks
        //For now exception would be thrown
        ns.merge(b1,
                new CompositeHook(
                        ConflictHook.of(new AnnotatingConflictHandler()),
                        new EditorHook(new ConflictValidatorProvider())
                ),
                CommitInfo.EMPTY);
    }

    /**
     * This testcase demonstrates that diff logic in merge part traverses node path
     * which are not affected by the commit
     * @throws Exception
     */
    @Test
    public void testDiff() throws Exception{
        createNodes("/oak:index/prop-a", "/oak:index/prop-b", "/etc/workflow");

        //1. Make some other changes so as to bump root rev=3
        createNodes("/fake/a");
        createNodes("/fake/b");

        //2 - Start change
        NodeBuilder b2 = ns.getRoot().builder();
        createNodes(b2, "/etc/workflow/instance1");

        tds.reset();
        //3. Merge which does a rebase
        ns.merge(b2, new CommitHook() {
            @NotNull
            public NodeState processCommit(NodeState before, NodeState after, CommitInfo info) throws CommitFailedException {
                NodeBuilder rb = after.builder();
                createNodes(rb, "/oak:index/prop-a/a1");

                //2.1 Commit some change under prop-
                //This cause diff in lastRev of base node state in ModifiedNodeState for
                //oak:index due to which when the base state is compared in ModifiedNodeState
                //then it fetches the new DocumentNodeState whose lastRev is greater than this.base.lastRev
                //but less then lastRev of the of readRevision. Where readRevision is the rev of root node when
                //rebase was performed

                // remember paths accessed so far
                List<String> paths = Lists.newArrayList(tds.paths);

                //This is not to be done in actual cases as CommitHooks are invoked in critical sections
                //and creating nodes from within CommitHooks would cause deadlock. This is done here to ensure
                //that changes are done when rebase has been performed and merge is about to happen
                createNodes("/oak:index/prop-b/b1");

                // reset accessed paths
                tds.reset();
                tds.paths.addAll(paths);

                //For now we the cache is disabled (size 0) so this is not required
                //ns.nodeCache.invalidateAll();

                return rb.getNodeState();
            }
        }, CommitInfo.EMPTY);

        //Assert that diff logic does not traverse to /oak:index/prop-b/b1 as
        //its not part of commit
        assertFalse(tds.paths.contains("/oak:index/prop-b/b1"));
    }

    // OAK-4403
    @Test
    public void diffWithPersistedBranch() throws Exception{
        createNodes("/content/a", "/etc/x", "var/x", "/etc/y");

        //#1 - Start making some changes
        NodeBuilder b = ns.getRoot().builder();
        createNodes(b, "/content/b");

        //#2 - Do lots of change so as to trigger branch creation
        //BranchState > Unmodified -> InMemory
        for (int i = 0; i <= UPDATE_LIMIT; i++) {
            b.child("content").child("a").child("c" + i);
        }

        //#3 -  In between push some changes to NodeStore
        NodeBuilder b2 = ns.getRoot().builder();
        b2.child("etc").child("x").setProperty("foo", 1);
        b2.child("var").remove();
        merge(b2);
        ns.runBackgroundOperations();

        createNodes(b, "/content/e");

        tds.reset();

        merge(b);

        //With the merge the diff logic should not be accessing the
        //paths which are not part of the current commit like /etc and /var
        assertThat(tds.paths, not(hasItem("/etc/x")));
        assertThat(tds.paths, not(hasItem("/var/x")));
    }

    private NodeState merge(NodeBuilder nb) throws CommitFailedException {
        NodeState result = ns.merge(nb, EmptyHook.INSTANCE, CommitInfo.EMPTY);
        prRev(result);
        ops();
        return result;
    }

    private void ops(){
        ns.runBackgroundOperations();
    }

    private NodeState createNodes(String... paths) throws CommitFailedException {
        NodeBuilder nb = ns.getRoot().builder();
        createNodes(nb, paths);
        return merge(nb);
    }

    private static void createNodes(NodeBuilder builder, String... paths) {
        for(String path : paths) {
            NodeBuilder cb = builder;
            for (String name : PathUtils.elements(path)) {
                cb = cb.child(name);
            }
        }
    }

    private void prRev(NodeState ns){
        if(ns instanceof DocumentNodeState){
            DocumentNodeState dns = ((DocumentNodeState) ns);
            LOG.info("Root at {} ({})", dns.getRootRevision(), dns.getLastRevision());
        }
    }


    private static class TestDocumentStore extends MemoryDocumentStore {
        final Set<String> paths = Sets.newHashSet();

        @Override
        public <T extends Document> T find(Collection<T> collection, String key) {
            if(collection == Collection.NODES){
                paths.add(Utils.getPathFromId(key));
            }
            return super.find(collection, key);
        }

        void reset(){
            paths.clear();
        }
    }
}
