/*
 * 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.
 */

package demo.dashboard;

import java.io.IOException;
import java.net.MalformedURLException;
import java.util.Map;

import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;
import javax.servlet.ServletContext;

import ilog.views.dashboard.IlvDashboardContext;
import ilog.views.dashboard.IlvDashboardDiagram;
import ilog.views.diagrammer.IlvDiagrammer;
import ilog.views.diagrammer.IlvDiagrammerException;
import ilog.views.sdm.IlvSDMView;

/**
 * This class defines the logic of the JViews Diagrammer Faces Dashboard sample.
 */
public class DashboardBean {

  public IlvDashboardDiagram getDashboard() throws MalformedURLException, IOException, IlvDiagrammerException {
    ExternalContext ctx = FacesContext.getCurrentInstance().getExternalContext();
    Map appMap = ctx.getApplicationMap();    
    BAMCockpit cockpit = (BAMCockpit)appMap.get("BAMCockpit");
    
    IlvDashboardDiagram dashboard;
    if (cockpit == null) {
      dashboard = new IlvDashboardDiagram(new IlvDashboardContext(), new IlvSDMView());      
      dashboard.readDashboard(ctx.getResource("/data/bam.idbd"));
      cockpit = new BAMCockpit(dashboard);
      appMap.put("BAMCockpit", cockpit);
      cockpit.start();
    } else
      dashboard = cockpit.getDashboard();
    return dashboard;
  }  
   
  private static class BAMCockpit implements Runnable {

    // delay between refreshes, in ms
    public  long ANIM_DELAY = 3000l; 
    // max variation at each refresh
    public  double DELTA = 10d;        
      // visitor array, each entry between 0 and 100
    public double[] visitors = { 10d, 20d, 30d, 20d };
    
    private IlvDashboardDiagram dashboard;
    
    private Thread thread;
    
    private boolean stopped = true;
    
    /**
     * @param dashboard the diagram to animate
     */
    public BAMCockpit(IlvDashboardDiagram dashboard) {
      this.dashboard = dashboard;
    }

    public void start() {
      if (stopped) {
        stopped = false;
        thread = new Thread(this);
        thread.start();
      }
    }
    
    public void stop() {
      stopped = true;
    }    
    
    // called by the thread
    public void run() {
      while (true && !stopped) {
        changeRandomValues();
        updateDashBoard();
        try {
          Thread.sleep(ANIM_DELAY);
        } catch (InterruptedException ex) {
        }
      }
    }
    
    public IlvDashboardDiagram getDashboard() {
      return dashboard;
    }

    /**
     * Animates the dashboard by changing some values
     */
    private void changeRandomValues() {
      for (int i=0; i<4; i++) {
        double delta = DELTA*(Math.random()-.5d);
        visitors[i] += delta;
        // bound changes
        if (visitors[i]<0) visitors[i] -= delta*2d;
        if (visitors[i]>100) visitors[i] -= delta*2d;
      }
    }    
    
    // update the dashboard symbols
    private void updateDashBoard() {
      dashboard.setAdjusting(true);
      
      // update the 4 bar charts
      Object v = dashboard.getObject("visitors");
      double totalVisitors = 0d;
      for (int i=0; i<4; i++) {
        dashboard.setObjectProperty(v, 
            "value"+(i+1),
            new Double(visitors[i]));
        totalVisitors += visitors[i];
      }
      
      //update total gauge
      Object yty1 = dashboard.getObject("yty_visitors");
      // normalize value 
      int total = (int)(totalVisitors/40d*1000d);   
      dashboard.setObjectProperty(yty1, "value", new Double(total/1000d));
      dashboard.setObjectProperty(yty1, "preset", new Double((Math.random()-0.5) + total/1000d));
      
      // update funnel1
      Object f1 = dashboard.getObject("website");
      total = (int) totalVisitors*550;
      dashboard.setObjectProperty(f1, "value1", new Integer(total));
      dashboard.setObjectProperty(f1, "value2", new Integer(total/4));
      dashboard.setObjectProperty(f1, "value3", new Integer(total/5));
      dashboard.setObjectProperty(f1, "value4", new Integer(total/50));

      // update opportunities
      Object o1 = dashboard.getObject("opportunities");
      total = (int) totalVisitors;
      dashboard.setObjectProperty(o1 , "value1", new Integer(total));
      dashboard.setObjectProperty(o1 , "value2", new Integer(total/4));
      dashboard.setObjectProperty(o1 , "value3", new Integer(total/5));
      dashboard.setObjectProperty(o1 , "value4", new Integer(total/50));

      //update opportunity gauge
      Object yty2 = dashboard.getObject("yty_business");
      // normalize value 
      Object old = dashboard.getObjectProperty(yty2, "value");
      int val = ((Number) old).intValue();
      //add last opportunities
      val = (val+total/50)%500;
      dashboard.setObjectProperty(yty2, "value", new Integer(val));
      dashboard.setObjectProperty(yty2, "preset", new Double((Math.random()-0.5)*20 + val));

      // update the pie chart
      Object revenues = dashboard.getObject("revenues");
      double rev_value = Math.random()*1000;
      dashboard.setObjectProperty(revenues , "USA", new Double(rev_value*3+Math.random()*50));
      dashboard.setObjectProperty(revenues , "Europe", new Double(rev_value*2+Math.random()*50));
      dashboard.setObjectProperty(revenues , "APAC", new Double(rev_value*1+Math.random()*50));
      dashboard.setObjectProperty(revenues , "ROW", new Double(rev_value*1+Math.random()*50));

      dashboard.setAdjusting(false);
    }
  }
}