//   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.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;

import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInstance;
import de.ugoe.cs.autoquest.tasktrees.treeifc.IUserSession;

/**
 * <p>
 * this is the default implementation of the interface {@link IUserSession}. It
 * does not do anything fancy except implementing the interface.
 * </p>
 * 
 * @author Patrick Harms
 */
class UserSession implements IUserSession {
    
    /**
     * <p>
     * default serial version UID
     * </p>
     */
    private static final long serialVersionUID = 1L;
    
    /**
     * <p>
     * the task instances belonging to the user session
     * </p>
     */
    private List<ITaskInstance> executedTasks = new ArrayList<ITaskInstance>();

    /* (non-Javadoc)
     * @see de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInstanceList#get(int)
     */
    @Override
    public ITaskInstance get(int index) {
        return executedTasks.get(index);
    }

    /* (non-Javadoc)
     * @see de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInstanceList#size()
     */
    @Override
    public int size() {
        return executedTasks.size();
    }

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

    /* (non-Javadoc)
     * @see de.ugoe.cs.autoquest.tasktrees.treeifc.IUserSession#getExecutedTasks()
     */
    @Override
    public List<ITaskInstance> getExecutedTasks() {
        return Collections.unmodifiableList(executedTasks);
    }

    /* (non-Javadoc)
     * @see de.ugoe.cs.autoquest.tasktrees.treeifc.IUserSession#equals(IUserSession)
     */
    @Override
    public boolean equals(IUserSession userSession) {
        // task instances are only equal if they are identical or if they have the same id
        // (may happen, if they are cloned)
        return (this == userSession) || (this.hashCode() == userSession.hashCode());
    }

    /* (non-Javadoc)
     * @see java.lang.Object#hashCode()
     */
    @Override
    public synchronized int hashCode() {
        return super.hashCode();
    }

    /* (non-Javadoc)
     * @see java.lang.Object#toString()
     */
    @Override
    public synchronized String toString() {
        return "session (" + executedTasks.size() + " task instances)";
    }

    /* (non-Javadoc)
     * @see java.lang.Object#clone()
     */
    @Override
    public synchronized IUserSession clone() {
        UserSession clone = null;
        try {
            clone = (UserSession) super.clone();

            clone.executedTasks = new LinkedList<ITaskInstance>();
            
            for (ITaskInstance child : executedTasks) {
                clone.executedTasks.add(child.clone());
            }

        }
        catch (CloneNotSupportedException e) {
            // this should never happen. Therefore simply dump the exception
            e.printStackTrace();
        }

        return clone;
    }

    /**
     * <p>
     * used internally to add a task instance to the user session
     * </p>
     * 
     * @param taskInstance the task instance to be added
     */
    void addExecutedTask(ITaskInstance taskInstance) {
        executedTasks.add(taskInstance);
    }

    /**
     * <p>
     * used internally to add a task instance to the user session at a specific position
     * </p>
     * 
     * @param index        the index the task instance shall be added to
     * @param taskInstance the task instance to be added
     */
    void addExecutedTask(int index, ITaskInstance taskInstance) {
        executedTasks.add(index, taskInstance);
    }

    /**
     * <p>
     * used internally to remove a task instance from the user session
     * </p>
     * 
     * @param index the index of the task instance to be removed
     */
    void removeExecutedTask(int index) {
        executedTasks.remove(index);
    }

}
