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

import static com.google.common.base.Suppliers.memoize;
import static com.google.common.collect.ImmutableSet.of;
import static com.google.common.collect.Maps.newHashMap;
import static com.google.common.collect.Sets.newHashSet;
import static java.util.Collections.emptySet;
import static javax.jcr.PropertyType.REFERENCE;
import static javax.jcr.PropertyType.WEAKREFERENCE;
import static org.apache.jackrabbit.JcrConstants.JCR_UUID;
import static org.apache.jackrabbit.oak.api.CommitFailedException.INTEGRITY;
import static org.apache.jackrabbit.oak.api.Type.STRING;
import static org.apache.jackrabbit.oak.api.Type.STRINGS;
import static org.apache.jackrabbit.oak.commons.PathUtils.concat;
import static org.apache.jackrabbit.oak.commons.PathUtils.isAbsolute;
import static org.apache.jackrabbit.oak.plugins.index.reference.NodeReferenceConstants.REF_NAME;
import static org.apache.jackrabbit.oak.plugins.index.reference.NodeReferenceConstants.WEAK_REF_NAME;
import static org.apache.jackrabbit.oak.plugins.memory.EmptyNodeState.MISSING_NODE;
import static org.apache.jackrabbit.oak.spi.version.VersionConstants.VERSION_STORE_PATH;

import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import com.google.common.base.Supplier;
import com.google.common.collect.Sets;

import org.apache.jackrabbit.oak.api.CommitFailedException;
import org.apache.jackrabbit.oak.api.PropertyState;
import org.apache.jackrabbit.oak.plugins.index.IndexEditor;
import org.apache.jackrabbit.oak.plugins.index.property.Multiplexers;
import org.apache.jackrabbit.oak.plugins.index.property.strategy.IndexStoreStrategy;
import org.apache.jackrabbit.oak.spi.commit.DefaultEditor;
import org.apache.jackrabbit.oak.spi.commit.Editor;
import org.apache.jackrabbit.oak.spi.mount.MountInfoProvider;
import org.apache.jackrabbit.oak.spi.state.NodeBuilder;
import org.apache.jackrabbit.oak.spi.state.NodeState;

/**
 * Index editor for keeping a references to a node up to date.
 * 
 */
class ReferenceEditor extends DefaultEditor implements IndexEditor {

    /** Parent editor, or {@code null} if this is the root editor. */
    private final ReferenceEditor parent;

    /** Name of this node, or {@code null} for the root node. */
    private final String name;

    /** Path of this editor, built lazily in {@link #getPath()}. */
    private String path;

    private final NodeState root;

    private final NodeBuilder definition;

    /**
     * <UUID, Set<paths-pointing-to-the-uuid>>
     */
    private final Map<String, Set<String>> newRefs;

    /**
     * <UUID, Set<paths-pointing-to-the-uuid>>
     */
    private final Map<String, Set<String>> rmRefs;

    /**
     * <UUID, Set<paths-pointing-to-the-uuid>>
     */
    private final Map<String, Set<String>> newWeakRefs;

    /**
     * <UUID, Set<paths-pointing-to-the-uuid>>
     */
    private final Map<String, Set<String>> rmWeakRefs;

    /**
     * set of removed Ids of nodes that have a :reference property. These UUIDs
     * need to be verified in the #after call
     */
    private final Set<String> rmIds;

    /**
     * set of ids that were added during this commit. we need it to reconcile
     * moves
     */
    private final Set<String> newIds;

    private final MountInfoProvider mountInfoProvider;

    /**
     * flag marking a reindex, case in which we don't need to keep track of the
     * newIds set
     */
    private boolean isReindex;

    public ReferenceEditor(NodeBuilder definition, NodeState root,MountInfoProvider mountInfoProvider) {
        this.parent = null;
        this.name = null;
        this.path = "/";
        this.definition = definition;
        this.root = root;
        this.newRefs = newHashMap();
        this.rmRefs = newHashMap();
        this.newWeakRefs = newHashMap();
        this.rmWeakRefs = newHashMap();
        this.rmIds = newHashSet();
        this.newIds = newHashSet();
        this.mountInfoProvider = mountInfoProvider;
    }

    private ReferenceEditor(ReferenceEditor parent, String name) {
        this.parent = parent;
        this.name = name;
        this.path = null;
        this.definition = parent.definition;
        this.root = parent.root;
        this.newRefs = parent.newRefs;
        this.rmRefs = parent.rmRefs;
        this.newWeakRefs = parent.newWeakRefs;
        this.rmWeakRefs = parent.rmWeakRefs;
        this.rmIds = parent.rmIds;
        this.newIds = parent.newIds;
        this.isReindex = parent.isReindex;
        this.mountInfoProvider = parent.mountInfoProvider;
    }

    /**
     * Returns the path of this node, building it lazily when first requested.
     */
    private String getPath() {
        if (path == null) {
            path = concat(parent.getPath(), name);
        }
        return path;
    }

    @Override
    public void enter(NodeState before, NodeState after)
            throws CommitFailedException {
        if (MISSING_NODE == before && parent == null) {
            isReindex = true;
        }
    }

    @Override
    public void leave(NodeState before, NodeState after)
            throws CommitFailedException {
        if (parent == null) {
            Set<IndexStoreStrategy> refStores = getStrategies(false, REF_NAME);
            Set<IndexStoreStrategy> weakRefStores = getStrategies(false, WEAK_REF_NAME);
            // update references
            for (Entry<String, Set<String>> ref : rmRefs.entrySet()) {
                String uuid = ref.getKey();
                Set<String> rm = ref.getValue();
                Set<String> add = emptySet();
                if (newRefs.containsKey(uuid)) {
                    add = newRefs.remove(uuid);
                }
                update(refStores, definition, REF_NAME, uuid, add, rm);
            }
            for (Entry<String, Set<String>> ref : newRefs.entrySet()) {
                String uuid = ref.getKey();
                if (rmIds.contains(uuid)) {
                    continue;
                }
                Set<String> add = ref.getValue();
                Set<String> rm = emptySet();
                update(refStores, definition, REF_NAME, uuid, add, rm);
            }

            checkReferentialIntegrity(refStores, root, definition.getNodeState(),
                    Sets.difference(rmIds, newIds));

            // update weak references
            for (Entry<String, Set<String>> ref : rmWeakRefs.entrySet()) {
                String uuid = ref.getKey();
                Set<String> rm = ref.getValue();
                Set<String> add = emptySet();
                if (newWeakRefs.containsKey(uuid)) {
                    add = newWeakRefs.remove(uuid);
                }
                update(weakRefStores, definition, WEAK_REF_NAME, uuid, add, rm);
            }
            for (Entry<String, Set<String>> ref : newWeakRefs.entrySet()) {
                String uuid = ref.getKey();
                Set<String> add = ref.getValue();
                Set<String> rm = emptySet();
                update(weakRefStores, definition, WEAK_REF_NAME, uuid, add, rm);
            }
        }
    }

    Set<IndexStoreStrategy> getStrategies(boolean unique, String index) {
        return Multiplexers.getStrategies(unique, mountInfoProvider,
                definition, index);
    }

    @Override
    public void propertyAdded(PropertyState after) {
        propertyChanged(null, after);
    }

    @Override
    public void propertyChanged(PropertyState before, PropertyState after) {

        if (before != null) {
            if (before.getType().tag() == REFERENCE) {
                if (!isVersionStorePath(getPath())) {
                    put(rmRefs, before.getValue(STRINGS),
                            concat(getPath(), before.getName()));
                }
            }
            if (before.getType().tag() == WEAKREFERENCE) {
                put(rmWeakRefs, before.getValue(STRINGS),
                        concat(getPath(), before.getName()));
            }
            if (JCR_UUID.equals(before.getName())) {
                // node remove + add -> changed uuid
                rmIds.add(before.getValue(STRING));
            }
        }
        if (after != null) {
            if (after.getType().tag() == REFERENCE) {
                if (!isVersionStorePath(getPath())) {
                    put(newRefs, after.getValue(STRINGS),
                            concat(getPath(), after.getName()));
                }
            }
            if (after.getType().tag() == WEAKREFERENCE) {
                put(newWeakRefs, after.getValue(STRINGS),
                        concat(getPath(), after.getName()));
            }
            if (JCR_UUID.equals(after.getName())) {
                // node remove + add -> changed uuid
                newIds.add(after.getValue(STRING));
            }
        }
    }

    @Override
    public void propertyDeleted(PropertyState before) {
        propertyChanged(before, null);
    }

    @Override
    public Editor childNodeAdded(String name, NodeState after) {
        String uuid = after.getString(JCR_UUID);
        if (!isReindex && uuid != null) {
            newIds.add(uuid);
        }
        return new ReferenceEditor(this, name);
    }

    @Override
    public Editor childNodeChanged(String name, NodeState before,
            NodeState after) {
        return new ReferenceEditor(this, name);
    }

    @Override
    public Editor childNodeDeleted(String name, NodeState before)
            throws CommitFailedException {
        String uuid = before.getString(JCR_UUID);
        if (uuid != null) {
            rmIds.add(uuid);
        }
        return new ReferenceEditor(this, name);
    }

    // ---------- Utils -----------------------------------------

    private static boolean isVersionStorePath(String oakPath) {
        return oakPath != null
                && oakPath.startsWith(VERSION_STORE_PATH);
    }

    private static void put(Map<String, Set<String>> map,
            Iterable<String> keys, String value) {
        String asRelative = isAbsolute(value) ? value.substring(1) : value;
        for (String key : keys) {
            Set<String> values = map.get(key);
            if (values == null) {
                values = newHashSet();
            }
            values.add(asRelative);
            map.put(key, values);
        }
    }

    private void update(Set<IndexStoreStrategy> refStores,
            NodeBuilder definition, String name, String key, Set<String> add,
            Set<String> rm) throws CommitFailedException {
        for (IndexStoreStrategy store : refStores) {
            Set<String> empty = of();
            for (String p : rm) {
                Supplier<NodeBuilder> index = memoize(() -> definition.child(store.getIndexNodeName()));
                store.update(index, p, name, definition, of(key), empty);
            }
            for (String p : add) {
                // TODO do we still need to encode the values?
                Supplier<NodeBuilder> index = memoize(() -> definition.child(store.getIndexNodeName()));
                store.update(index, p, name, definition, empty, of(key));
            }
        }
    }

    private static boolean hasReferences(IndexStoreStrategy refStore,
                                  NodeState root,
                                  NodeState definition,
                                  String name,
                                  String key) {
        return definition.hasChildNode(name)
                && refStore.count(root, definition, of(key), 1) > 0;
    }

    private static void checkReferentialIntegrity(Set<IndexStoreStrategy> refStores,
                                           NodeState root,
                                           NodeState definition,
                                           Set<String> idsOfRemovedNodes)
            throws CommitFailedException {
        for (IndexStoreStrategy store : refStores) {
            for (String id : idsOfRemovedNodes) {
                if (hasReferences(store, root, definition, REF_NAME, id)) {
                    throw new CommitFailedException(INTEGRITY, 1,
                            "Unable to delete referenced node: " + id);
                }
            }
        }
    }
}
