//   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.sequences;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;

import de.ugoe.cs.autoquest.CommandHelpers;
import de.ugoe.cs.autoquest.SequenceInstanceOf;
import de.ugoe.cs.autoquest.eventcore.Event;
import de.ugoe.cs.util.console.Command;
import de.ugoe.cs.util.console.GlobalDataContainer;

/**
 * <p>
 * TODO comment
 * </p>
 * 
 * @author Patrick Harms
 * @version 1.0
 */
public class CMDeventStatistics implements Command {

    /*
     * (non-Javadoc)
     * 
     * @see de.ugoe.cs.util.console.Command#run(java.util.List)
     */
    @SuppressWarnings("unchecked")
    @Override
    public void run(List<Object> parameters) {
        List<String> sequenceNames = new ArrayList<>(parameters.size());
        try {
            for (Object parameter : parameters) {
                sequenceNames.add((String) parameter);
            }
        }
        catch (Exception e) {
            throw new IllegalArgumentException();
        }

        List<Collection<List<Event>>> sequences = new ArrayList<>(sequenceNames.size());
        
        for (String sequenceName : sequenceNames) {
            Object dataObject = GlobalDataContainer.getInstance().getData(sequenceName);
            if (dataObject == null) {
                CommandHelpers.objectNotFoundMessage(sequenceName);
                return;
            }
            if (!SequenceInstanceOf.isCollectionOfSequences(dataObject)) {
                CommandHelpers.objectNotType(sequenceName, "Collection<List<Event<?>>>");
                return;
            }
            
            sequences.add((Collection<List<Event>>) dataObject);
        }
        
        Map<String, Map<String, Integer>> counters = new TreeMap<>();
        
        for (int i = 0; i < sequences.size(); i++) {
            String sequenceName = sequenceNames.get(i);
            for (List<Event> sequence : sequences.get(i)) {
                for (Event event : sequence) {
                    String eventId = event.getType().toString() + "." + event.getTarget().toString();
                    Map<String, Integer> counterMap = counters.get(eventId);
                    
                    if (counterMap == null) {
                        counterMap = new HashMap<>();
                        counters.put(eventId, counterMap);
                    }
                    
                    Integer counter = counterMap.get(sequenceName);
                    if (counter == null) {
                        counterMap.put(sequenceName, 1);
                    }
                    else {
                        counterMap.put(sequenceName, counter + 1);
                    }
                }
            }
        }
        
        int maxEventNameLength = 0;
        for (Map.Entry<String, Map<String, Integer>> sequenceStats : counters.entrySet()) {
            maxEventNameLength = Math.max(maxEventNameLength, sequenceStats.getKey().length());
        }

        List<StringBuffer> lines = new LinkedList<>();
        for (Map.Entry<String, Map<String, Integer>> sequenceStats : counters.entrySet()) {
            StringBuffer line = new StringBuffer();
            line.append(sequenceStats.getKey());
            
            for (int i = sequenceStats.getKey().length(); i < maxEventNameLength; i++) {
                line.append(' ');
            }
            
            for (int i = 0; i < sequenceNames.size(); i++) {
                String sequenceName = sequenceNames.get(i);
                String numberStr = "";
                
                if (sequenceStats.getValue().get(sequenceName) != null) {
                    int value = sequenceStats.getValue().get(sequenceName);
                    numberStr += value;
                    numberStr += " (";
                    numberStr += ((float) value) / sequences.get(i).size();
                    numberStr += ")";
                }
                
                line.append(" | ");
                line.append(numberStr);
                
                for (int j = numberStr.length(); j < sequenceName.length(); j++) {
                    line.append(' ');
                }
            }
            
            lines.add(line);
        }
        
        for (int i = 0; i < maxEventNameLength; i++) {
            System.out.print(' ');
        }
        
        for (String sequenceName : sequenceNames) {
            System.out.print(" | " + sequenceName);
        }
        
        System.out.println();
        
        for (StringBuffer line : lines) {
            System.out.println(line);
        }
    }

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

}
