/*
 * Licensed Materials - Property of Rogue Wave Software, Inc. 
 * © Copyright Rogue Wave Software, Inc. 2014, 2015 
 * © Copyright IBM Corp. 2009, 2014
 * © Copyright ILOG 1996, 2009
 * All Rights Reserved.
 *
 * Note to U.S. Government Users Restricted Rights:
 * The Software and Documentation were developed at private expense and
 * are "Commercial Items" as that term is defined at 48 CFR 2.101,
 * consisting of "Commercial Computer Software" and
 * "Commercial Computer Software Documentation", as such terms are
 * used in 48 CFR 12.212 or 48 CFR 227.7202-1 through 227.7202-4,
 * as applicable.
 */

import ilog.views.dashboard.IlvDashboardDiagram;
import ilog.views.dashboard.IlvDashboardSymbol;
import ilog.views.dashboard.IlvDashboardSymbolIterator;
import ilog.views.dashboard.IlvDashboardSymbol.Parameter;
import ilog.views.sdm.IlvSDMModel;
import ilog.views.util.swing.IlvSwingUtil;

import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Timer;
import java.util.TimerTask;
import java.util.Vector;




/**
 * The supervisor is associated to a dashboard. It will introspect it in order to get
 * the parameters to update, and it will periodically request values for those parameters to the simulator
 */
public class Supervisor {

    // the time for periodic updates.
    private Timer timer = null;
    
    // storage for the parameters to update and to request to simulator
    private Hashtable mapping = null;
    
    // the dashboard associated with this supervisor
    private IlvDashboardDiagram dashboard = null;
    private String name;
    
    // the simulator to request values
    private Simulator simulator = null;
    
    /**
     * Creates the supervisor for the specified dashboard. It will update data in this dashboard
     * according to the specified period. Values will be asked to the given simulator
     */
    public Supervisor(String name,IlvDashboardDiagram dashboard,int period,Simulator simulator) {
        this.name = name;
        this.dashboard = dashboard;
        this.simulator = simulator;
        mapping = new Hashtable();
        
        // get parameters from the dashboard in order to update/request them later
        extractParameters();
        
        // creates a task to update the model periodically
        TimerTask task =  new TimerTask(){
          public void run() {
            IlvSwingUtil.invokeAndWait(new Runnable() { 
              public void run() { 
                updateModel();
              } 
            });     

          }  
        };
        // creates the timer that will perform the task. It will start in 2s
        timer = new Timer();
        timer.schedule(task,2000,period);
    }

    
    /**
     * Extract the mapped symbol parameters from the dashboard and store them
     * in order to be able to request their value to the simulator and to 
     * update the model later  
     */
    private void extractParameters() {
        // go through  all symbols of the dashboard
        IlvDashboardSymbolIterator symbols = dashboard.getSymbols();        
        while( symbols.hasNext() ){
            IlvDashboardSymbol symbol = symbols.next();
            
            // go through parameters of the symbol
            int count = symbol.getParameterCount();
            if(count>0){
                int mapped = 0;
                Vector params = new Vector(); // create a list for the mapped parameters
                for(int i=0;i<count;i++){                    
                    Parameter param = symbol.getParameter(i);
                    
                    // if parameter is mapped then add the mapping name into list
                    if(param.isMapped()){
                        mapped++;
                        params.add( symbol.getParameterMapping(param) );
                    }
                }
                
                // associated the list to the symbol
                if(mapped>0){
                    mapping.put(symbol.getID(), params);
                }
            }
        }
    }
    
    /**
     * Update the model with new parameter's values. Value are asked to the simulator
     */
    private void updateModel(){
        
        IlvSDMModel model = dashboard.getView().getModel();
       
        // go throught the list of symbols which have mapped parameters
        for (Enumeration e = mapping.keys() ; e.hasMoreElements() ;) {
            String symbolID = (String)e.nextElement();
            // get the mapped parameters of the symbol
            Vector params = (Vector)mapping.get(symbolID);
            if(params!=null){
                
                Object symbol = model.getObject(symbolID);
                
                // for each mapped parameters we ask a value to the simulator
                // and we update the model with this new value
                for(int i=0;i<params.size();i++){
                    String mapName = (String)params.get(i); // get the name of the param
                    Object value = simulator.getValue(mapName); // request the value for this param
                    if(value!=null){
                        model.setObjectProperty(symbol, mapName, value); // update the model
                    }
                    
                }
            }
        }

        
    }
    


}