//   Copyright 2015 Georg-August-Universität Göttingen, Germany
//
//   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 de.ugoe.cs.autoquest.eventcore;

import java.util.List;

/**
 * <p>
 * This interface can be used to wrap tree like event target structures. This allows rather
 * flexible implementations of such structures and can either be rather concrete, e.g., for
 * GUI models, or rather generic for any type of event target. The interface provides a way to
 * traverse the target structure by retrieving a traverser.
 * </p>
 * 
 * @author Patrick Harms
 */
public interface IHierarchicalEventTargetModel<T extends IHierarchicalEventTarget>  {

    /**
     * <p>
     * Returns all children of the provided event target or null, if it does not have any or the
     * node is unknown.
     * </p>
     * 
     * @param eventTarget
     *            the event target of which the children shall be returned
     * 
     * @return As described
     */
    List<T> getChildren(T eventTarget);

    /**
     * <p>
     * Returns the parent event target of the provided one or null, if it does not have a
     * parent (i.e. if it is a root node) or if the node is unknown.
     * </p>
     * 
     * @param eventTarget
     *            the event target of which the parent shall be returned
     * 
     * @return As described
     */
    T getParent(T eventTarget);

    /**
     * <p>
     * Returns all root event targets of the model or an empty list, if the model is empty
     * </p>
     * 
     * @return As described
     */
    List<T> getRootElements();

    
    /**
     * returns a traverser for the event target model to have efficient access to the tree of
     * event targets without having direct access.
     * 
     * @return a traverser
     */
    Traverser<T> getTraverser();

    /**
     * returns a traverser for the event target model starting at the given event target. Returns
     * null, if the event target is not part of the model.
     * 
     * @return a traverser
     */
    Traverser<T> getTraverser(T startingAt);

    
    /**
     * <p>
     * This interface defines the methods to be provided by model traversers
     * </p>
     * 
     * @author Patrick Harms
     */
    public interface Traverser<T> {

        /**
         * <p>
         * returns the first child of the current event target. On the first call of this method on
         * the traverser the first of the root event targets of the event target model is returned.
         * If the current event target does not have children, the method returns null. If the
         * event target model is empty, then a call to this method will return null. The returned
         * event target is the next one the traverser points to.
         * </p>
         *
         * @return as described.
         */
        T firstChild();

        /**
         * <p>
         * returns true, if the current event target has a first child, i.e. if the next call to the
         * method {@link #firstChild()} would return an event target or null.
         * </p>
         *
         * @return as described
         */
        boolean hasFirstChild();

        /**
         * <p>
         * returns the next sibling of the current event target. If there is no further sibling,
         * null is returned. If the current event target is one of the root nodes, the next root
         * node of the event target model is returned. The returned event target is the next one
         * the traverser points to.
         * </p>
         *
         * @return as described
         */
        T nextSibling();

        /**
         * <p>
         * returns true, if the current event target has a further sibling, i.e. if a call to the
         * method {@link #nextSibling()} will return an event target
         * </p>
         *
         * @return as described
         */
        boolean hasNextSibling();

        /**
         * <p>
         * returns the parent event target of the current event target. If the current event target
         * is a root node, null is returned. If there is no current event target yet as the method
         * {@link #firstChild()} was not called yet, null is returned.
         * </p>
         *
         * @return as described
         */
        T parent();

    }
}
