//   Copyright 2012 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.tasktrees.treeimpl;

import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;

import de.ugoe.cs.autoquest.tasktrees.treeifc.IIterationInstance;
import de.ugoe.cs.autoquest.tasktrees.treeifc.ISequence;
import de.ugoe.cs.autoquest.tasktrees.treeifc.ISequenceInstance;
import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInstance;

/**
 * <p>
 * Default implementation of {@link IIterationInstance}.
 * </p>
 * 
 * @author Patrick Harms
 */
class SequenceInstance extends TaskInstance implements ISequenceInstance {

    /**
     * <p>
     * default serial version UID
     * </p>
     */
    private static final long serialVersionUID = 1L;

    /**
     * <p>
     * the children of this task instance which are task instances, as well
     * </p>
     */
    private List<ITaskInstance> children;

    /**
     * <p>
     * initializes this instance with the respective task model
     * </p>
     *
     * @param task  the task of which this is an instance
     */
    SequenceInstance(ISequence task) {
        super(task);
    }

    /* (non-Javadoc)
     * @see de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInstance#getChildren()
     */
    public synchronized List<ITaskInstance> getChildren() {
        if (children == null) {
            children = new LinkedList<ITaskInstance>();
        }

        return Collections.unmodifiableList(children);
    }

    /* (non-Javadoc)
     * @see de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInstanceList#get(int)
     */
    @Override
    public synchronized ITaskInstance get(int index) {
        if (children == null) {
            throw new IndexOutOfBoundsException(Integer.toString(index));
        }
        else {
            return children.get(index);
        }
    }

    /* (non-Javadoc)
     * @see de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInstanceList#size()
     */
    @Override
    public synchronized int size() {
        if (children == null) {
            return 0;
        }
        else {
            return children.size();
        }
    }

    /* (non-Javadoc)
     * @see java.lang.Iterable#iterator()
     */
    @Override
    public Iterator<ITaskInstance> iterator() {
        return getChildren().iterator();
    }

    /* (non-Javadoc)
     * @see de.ugoe.cs.autoquest.tasktrees.treeifc.ISequenceInstance#getSequence()
     */
    @Override
    public ISequence getSequence() {
        return (ISequence) super.getTask();
    }

    /* (non-Javadoc)
     * @see de.ugoe.cs.autoquest.tasktrees.treeimpl.ISequenceInstance#clone()
     */
    @Override
    public synchronized ISequenceInstance clone() {
        SequenceInstance clone = (SequenceInstance) super.clone();

        if (children != null) {
            clone.children = new LinkedList<ITaskInstance>();

            for (ITaskInstance child : children) {
                clone.children.add(child.clone());
            }
        }

        return clone;
    }

    /**
     * <p>
     * used to add a child to this task instance
     * </p>
     * 
     * @param child the new child of this instance
     */
    synchronized void addChild(ITaskInstance child) {
        if (children == null) {
            children = new LinkedList<ITaskInstance>();
        }

        children.add(child);
    }

    /**
     * <p>
     * used to add a child to this task instance at a specific position
     * </p>
     * 
     * @param index the position of the new child in the list of children
     * @param child the new child of this instance
     */
    synchronized void addChild(int index, ITaskInstance child) {
        if (children == null) {
            children = new LinkedList<ITaskInstance>();
        }

        children.add(index, child);
    }

    /**
     * <p>
     * removes a child from this task instance at a specific position
     * </p>
     * 
     * @param index the position of the child to be removed
     * 
     * @return the child removed from the children of this instance
     */
    synchronized ITaskInstance removeChild(int index) {
        if (children != null) {
            return children.remove(index);
        }
        else {
            throw new IllegalArgumentException
                ("this task instance does not have children that can be removed");
        }
    }

}
