//   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.commands.usability;

import java.util.HashSet;
import java.util.List;
import java.util.Set;

import de.ugoe.cs.autoquest.CommandHelpers;
import de.ugoe.cs.autoquest.tasktrees.treeifc.DefaultTaskInstanceTraversingVisitor;
import de.ugoe.cs.autoquest.tasktrees.treeifc.IEventTask;
import de.ugoe.cs.autoquest.tasktrees.treeifc.IEventTaskInstance;
import de.ugoe.cs.autoquest.tasktrees.treeifc.IIteration;
import de.ugoe.cs.autoquest.tasktrees.treeifc.IOptional;
import de.ugoe.cs.autoquest.tasktrees.treeifc.ISelection;
import de.ugoe.cs.autoquest.tasktrees.treeifc.ISequence;
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.TaskMetric;
import de.ugoe.cs.util.console.Command;
import de.ugoe.cs.util.console.Console;
import de.ugoe.cs.util.console.GlobalDataContainer;

/**
 * <p>
 * This command provides statistical information about a given task tree.
 * </p>
 * 
 * @author Patrick Harms
 * @version 1.0
 */
public class CMDtaskTreeStatistics implements Command {

    /*
     * (non-Javadoc)
     * 
     * @see de.ugoe.cs.util.console.Command#help()
     */
    @Override
    public String help() {
        return "taskTreeStatistics <tasktree>";
    }

    /*
     * (non-Javadoc)
     * 
     * @see de.ugoe.cs.util.console.Command#run(java.util.List)
     */
    @Override
    public void run(List<Object> parameters) {
        String tasktreeName;
        try {
            tasktreeName = (String) parameters.get(0);
        }
        catch (Exception e) {
            throw new IllegalArgumentException("must provide a task tree name");
        }

        Object dataObject = GlobalDataContainer.getInstance().getData(tasktreeName);
        if (dataObject == null) {
            CommandHelpers.objectNotFoundMessage(tasktreeName);
            return;
        }
        if (!(dataObject instanceof ITaskModel)) {
            CommandHelpers.objectNotType(tasktreeName, "ITaskModel");
            return;
        }

        ITaskModel taskModel = (ITaskModel) dataObject;

        int taskCount = 0;
        int allTasks = taskModel.getTasks().size();
        Set<IEventTaskInstance> coveredEvents = new HashSet<IEventTaskInstance>();
        int allEvents = 0;
        
        int noOfEventTasks = 0;
        int noOfSequences = 0;
        int noOfIterations = 0;
        int noOfSelections = 0;
        int noOfOptionals = 0;
        
        for (ITask task : taskModel.getTasks()) {
            int covQuant =
                taskModel.getTaskInfo(task).getMeasureValue(TaskMetric.EVENT_COVERAGE_QUANTILE);
            
            if (covQuant >= 950) {
                taskCount++;
                getCoveredEvents(task, coveredEvents);
            }
            
            if (task instanceof IEventTask) {
                noOfEventTasks++;
                allEvents += task.getInstances().size();
            }
            else if (task instanceof ISequence) {
                noOfSequences++;
            }
            else if (task instanceof IIteration) {
                noOfIterations++;
            }
            else if (task instanceof ISelection) {
                noOfSelections++;
            }
            else if (task instanceof IOptional) {
                noOfOptionals++;
            }
        }
        
        Console.println(noOfEventTasks + " eventTasks, " + noOfSequences + " sequences, " +
                        noOfIterations + " iterations, " + noOfSelections + " selections, " +
                        noOfOptionals + " optionals");
        Console.println(taskCount + " of " + allTasks + " tasks (" + (taskCount * 100 / allTasks) +
                        "%) covered " + coveredEvents.size() + " of " + allEvents +
                        " recorded events (" + (coveredEvents.size() * 100 / allEvents) + "%)");
    }

    /**
     * <p>
     * convenience method to determine the number of covered events by a task
     * </p>
     *
     * @param task          the task to count the covered events for
     * @param coveredEvents the events covered by the task (in/out parameter)
     */
    private void getCoveredEvents(ITask task, final Set<IEventTaskInstance> coveredEvents) {
        for (ITaskInstance instance : task.getInstances()) {
            instance.accept(new DefaultTaskInstanceTraversingVisitor() {
                @Override
                public void visit(IEventTaskInstance eventTaskInstance) {
                    coveredEvents.add(eventTaskInstance);
                }
            });
        }
    }

}
