/*
 * 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.commons.configuration2.tree;

import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

/**
 * <p>
 * A class which allows an {@link InMemoryNodeModel} to associate arbitrary objects with nodes.
 * </p>
 * <p>
 * Some special configuration implementations need additional data to be stored with their nodes structure. We call such
 * data &quot;references&quot; because objects required by a configuration are referenced. In such constellations, it is
 * necessary to keep track about the nodes associated with references even if they are replaced by others during an
 * update operation of the model. This is the task of this class.
 * </p>
 * <p>
 * Basically, an instance manages a map associating nodes with reference objects. When a node is replaced the map gets
 * updated. References becoming orphans because the nodes pointing to them were removed are tracked, too. They may be of
 * importance for special configuration implementations as they might require additional updates. A concrete use case
 * for this class is {@code XMLConfiguration} which stores the DOM nodes represented by configuration nodes as
 * references.
 * </p>
 * <p>
 * Implementation note: This class is intended to work in a concurrent environment. Instances are immutable. The
 * represented state can be updated by creating new instances which are then stored by the owning node model.
 * </p>
 */
final class ReferenceTracker {
    /** A map with reference data. */
    private final Map<ImmutableNode, Object> references;

    /** A list with the removed references. */
    private final List<Object> removedReferences;

    /**
     * Creates a new instance of {@code ReferenceTracker}. This instance does not yet contain any data about references.
     */
    public ReferenceTracker() {
        this(Collections.<ImmutableNode, Object>emptyMap(), Collections.emptyList());
    }

    /**
     * Creates a new instance of {@code ReferenceTracker} and sets the data to be managed. This constructor is used
     * internally when references are updated.
     *
     * @param refs the references
     * @param removedRefs the removed references
     */
    private ReferenceTracker(final Map<ImmutableNode, Object> refs, final List<Object> removedRefs) {
        references = refs;
        removedReferences = removedRefs;
    }

    /**
     * Adds all references stored in the passed in map to the managed references. A new instance is created managing this
     * new set of references.
     *
     * @param refs the references to be added
     * @return the new instance
     */
    public ReferenceTracker addReferences(final Map<ImmutableNode, ?> refs) {
        final Map<ImmutableNode, Object> newRefs = new HashMap<>(references);
        newRefs.putAll(refs);
        return new ReferenceTracker(newRefs, removedReferences);
    }

    /**
     * Gets the reference object associated with the given node.
     *
     * @param node the node
     * @return the reference object for this node or <b>null</b>
     */
    public Object getReference(final ImmutableNode node) {
        return references.get(node);
    }

    /**
     * Gets the list with removed references. This list is immutable.
     *
     * @return the list with removed references
     */
    public List<Object> getRemovedReferences() {
        return Collections.unmodifiableList(removedReferences);
    }

    /**
     * Updates the references managed by this object at the end of a model transaction. This method is called by the
     * transaction with the nodes that have been replaced by others and the nodes that have been removed. The internal data
     * structures are updated correspondingly.
     *
     * @param replacedNodes the map with nodes that have been replaced
     * @param removedNodes the list with nodes that have been removed
     * @return the new instance
     */
    public ReferenceTracker updateReferences(final Map<ImmutableNode, ImmutableNode> replacedNodes, final Collection<ImmutableNode> removedNodes) {
        if (!references.isEmpty()) {
            Map<ImmutableNode, Object> newRefs = null;
            for (final Map.Entry<ImmutableNode, ImmutableNode> e : replacedNodes.entrySet()) {
                final Object ref = references.get(e.getKey());
                if (ref != null) {
                    if (newRefs == null) {
                        newRefs = new HashMap<>(references);
                    }
                    newRefs.put(e.getValue(), ref);
                    newRefs.remove(e.getKey());
                }
            }

            List<Object> newRemovedRefs = newRefs != null ? new LinkedList<>(removedReferences) : null;
            for (final ImmutableNode node : removedNodes) {
                final Object ref = references.get(node);
                if (ref != null) {
                    if (newRefs == null) {
                        newRefs = new HashMap<>(references);
                    }
                    newRefs.remove(node);
                    if (newRemovedRefs == null) {
                        newRemovedRefs = new LinkedList<>(removedReferences);
                    }
                    newRemovedRefs.add(ref);
                }
            }

            if (newRefs != null) {
                return new ReferenceTracker(newRefs, newRemovedRefs);
            }
        }

        return this;
    }
}
