/*
 * Copyright 2016-present Open Networking Laboratory
 *
 * Licensed 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.onosproject.store.service;

import java.util.Map;

import javax.annotation.concurrent.NotThreadSafe;

/**
 * A hierarchical <a href="https://en.wikipedia.org/wiki/Document_Object_Model">document tree</a> data structure.
 *
 * @param <V> document tree value type
 */
@NotThreadSafe
public interface DocumentTree<V> {

    /**
     * Returns the {@link DocumentPath path} to root of the tree.
     *
     * @return path to root of the tree
     */
    DocumentPath root();

    /**
     * Returns the child values for this node.
     *
     * @param path path to the node
     * @return mapping from a child name to its value
     * @throws NoSuchDocumentPathException if the path does not point to a valid node
     */
    Map<String, Versioned<V>> getChildren(DocumentPath path);

    /**
     * Returns a document tree node.
     *
     * @param path path to node
     * @return node value or {@code null} if path does not point to a valid node
     */
    Versioned<V> get(DocumentPath path);

    /**
     * Creates or updates a document tree node.
     *
     * @param path path for the node to create or update
     * @param value the non-null value to be associated with the key
     * @return the previous mapping or {@code null} if there was no previous mapping
     * @throws NoSuchDocumentPathException if the parent node (for the node to create/update) does not exist
     */
    Versioned<V> set(DocumentPath path, V value);

    /**
     * Creates a document tree node if one does not exist already.
     *
     * @param path path for the node to create
     * @param value the non-null value to be associated with the key
     * @return returns {@code true} if the mapping could be added successfully, {@code false} otherwise
     * @throws NoSuchDocumentPathException if the parent node (for the node to create) does not exist
     */
    boolean create(DocumentPath path, V value);

    /**
     * Conditionally updates a tree node if the current version matches a specified version.
     *
     * @param path path for the node to create
     * @param newValue the non-null value to be associated with the key
     * @param version current version of the value for update to occur
     * @return returns {@code true} if the update was made and the tree was modified, {@code false} otherwise
     * @throws NoSuchDocumentPathException if the parent node (for the node to create) does not exist
     */
    boolean replace(DocumentPath path, V newValue, long version);

    /**
     * Conditionally updates a tree node if the current value matches a specified value.
     *
     * @param path path for the node to create
     * @param newValue the non-null value to be associated with the key
     * @param currentValue current value for update to occur
     * @return returns {@code true} if the update was made and the tree was modified, {@code false} otherwise.
     * This method returns {@code false} if the newValue and currentValue are same.
     * @throws NoSuchDocumentPathException if the parent node (for the node to create) does not exist
     */
    boolean replace(DocumentPath path, V newValue, V currentValue);

    /**
     * Removes the node with the specified path.
     *
     * @param path path for the node to remove
     * @return the previous value of the node or {@code null} if it did not exist
     * @throws IllegalDocumentModificationException if the remove to be removed
     */
    Versioned<V> removeNode(DocumentPath path);

    /**
     * Registers a listener to be notified when a subtree rooted at the specified path
     * is modified.
     *
     * @param path path to root of subtree to monitor for updates
     * @param listener listener to be notified
     */
    void addListener(DocumentPath path, DocumentTreeListener<V> listener);

    /**
     * Unregisters a previously added listener.
     *
     * @param listener listener to unregister
     */
    void removeListener(DocumentTreeListener<V> listener);

    /**
     * Registers a listener to be notified when the tree is modified.
     *
     * @param listener listener to be notified
     */
    default void addListener(DocumentTreeListener<V> listener) {
        addListener(root(), listener);
    }
}
