//   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.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import de.ugoe.cs.autoquest.tasktrees.treeifc.IMarkingTemporalRelationship;
import de.ugoe.cs.autoquest.tasktrees.treeifc.IStructuringTemporalRelationship;
import de.ugoe.cs.autoquest.tasktrees.treeifc.ITask;
import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInstance;
import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskModel;
import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInfo;
import de.ugoe.cs.autoquest.tasktrees.treeifc.IUserSession;

/**
 * <p>
 * this is the default implementation of the interface {@link ITaskModel}. It
 * does not do anything fancy except implementing the interface.
 * </p>
 * 
 * @author Patrick Harms
 */
class TaskModel implements ITaskModel {
    
    /**
     * <p>
     * default serial version UID
     * </p>
     */
    private static final long serialVersionUID = 1L;

    /**
     * <p>
     * the user sessions belonging to the model
     * </p>
     */
    private List<IUserSession> userSessions;

    /**
     * <p>
     * the tasks contained in the user session belonging to the model as well as statistical infos
     * about them
     * </p>
     */
    private Map<ITask, TaskInfo> taskMap = new HashMap<ITask, TaskInfo>();

    /**
     * <p>
     * initializes the task model with the user sessions out of which the tasks are extracted
     * </p>
     * 
     * @param userSessions as described
     */
    TaskModel(List<IUserSession> userSessions) {
        if ((userSessions == null) || (userSessions.size() == 0)) {
            throw new IllegalArgumentException("user sessions must not be null");
        }
        
        this.userSessions = userSessions;
        
        for (IUserSession session : this.userSessions) {
            for (ITaskInstance taskInstance : session) {
                addTaskToMap(taskInstance.getTask());
            }
        }
    }


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


    /* (non-Javadoc)
     * @see de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskModel#getTasks()
     */
    @Override
    public Collection<ITask> getTasks() {
        return Collections.unmodifiableCollection(taskMap.keySet());
    }


    /* (non-Javadoc)
     * @see de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskModel#getTaskInfo(ITask)
     */
    @Override
    public ITaskInfo getTaskInfo(ITask task) {
        return taskMap.get(task);
    }

    /* (non-Javadoc)
     * @see java.lang.Object#clone()
     */
    @Override
    public TaskModel clone() {
        return new TaskModel(userSessions);
    }

    /**
     * <p>
     * internal convenience method to build the task model during initialization
     * </p>
     */
    private void addTaskToMap(ITask task) {
        TaskInfo taskInfo = taskMap.get(task);

        if (taskInfo == null) {
            taskInfo = new TaskInfo(task);
            taskMap.put(task, taskInfo);
        }

        if (task instanceof IStructuringTemporalRelationship) {
            for (ITask child : ((IStructuringTemporalRelationship) task).getChildren()) {
                addTaskToMap(child);
            }
        }
        else if (task instanceof IMarkingTemporalRelationship) {
            addTaskToMap(((IMarkingTemporalRelationship) task).getMarkedTask());
        }
    }

}
