/*
 * 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.IlvDashboardContext;
import ilog.views.dashboard.IlvDashboardDiagram;
import ilog.views.diagrammer.IlvDiagrammerException;
import ilog.views.diagrammer.internal.AppletStringPropertyEditor;
import ilog.views.util.beans.IlvPropertyEditorManager;
import ilog.views.util.IlvProductUtil;
import ilog.views.util.IlvResourceUtil;
import ilog.views.util.swing.IlvSwingUtil;

import java.io.IOException;
import java.net.URL;

import javax.swing.JApplet;
import javax.swing.JFrame;


/**
 * This is the entry point of the BAM demo. 
 */
public class BAMCockpit extends JApplet implements Runnable{

  static {
    // This applet is designed to run only with default resource bundle
    // and various selected other resource bundles.
    // Setting the available resource suffixes avoids that the applet
    // tries to load resource bundles for other locales over the net,
    // even if the current locale of the browser is different.
    if (IlvResourceUtil.isInApplet())
      IlvResourceUtil.setAvailableResourceSuffixes("", "_ja");

    // This sample uses JViews Diagrammer features. When deploying an
    // application that includes this code, you need to be in possession
    // of a Rogue Wave JViews Diagrammer Deployment license.
    IlvProductUtil.DeploymentLicenseRequired(
        IlvProductUtil.JViews_Diagrammer_Deployment);
  }


  /**
   * Entry point: loads the dashboard and display it
   * @param args (unused)
   */
  public static void main(String[] args) {
    IlvSwingUtil.invokeAndWait(new Runnable() {
        public void run() {
          BAMCockpit dashboard = new BAMCockpit();
          dashboard._isApplet = false; 
          dashboard.init();
          dashboard.start();
        }
      });
  }
    
  /////////////////////////////////////////////////////////////
  
  
  // delay between refreshes, in ms
  public  long ANIM_DELAY = 1000l; // real time: try 0l
  // max variation at each refresh
  public  double DELTA = 10d;        // real time: try 2d
    // visitor array, each entry between 0 and 100
  public double[] _visitors = { 10d, 20d, 30d, 20d };
  

  private IlvDashboardDiagram _dashboard;
  private Thread _animationThread;
  private boolean _isApplet = true;
  
  /**
   * Creates the BAM dashboard.
   */
  public BAMCockpit() {
  }

  /**
   * Initializes the application/applet.
   */

  public void init() {
    IlvSwingUtil.invokeAndWait(new Runnable() { 
        public void run() { 
          createGUI(); 
        } 
    });     
  }
  
  public void createGUI() {
    // the path to the idbd file (which defines the dashboard)
    String path = "data/bam.idbd";

    IlvDashboardContext context = new IlvDashboardContext();
    // create the diagram
    _dashboard = new IlvDashboardDiagram(context);
    URL url = null;
    try {
      if (_isApplet) {
        url = new URL(getDocumentBase(), path);
        IlvPropertyEditorManager.registerEditor(String.class, AppletStringPropertyEditor.class);
      } else {
        // In application, we can load manually the palette. E.g.: 
        //        context.loadPalettes(new URL("file:myPalette.jar"));
        // Here this is useless because the palette is already in the CLASSPATH
        
        url = new URL("file:./" + path);
      }
      _dashboard.readDashboard(url);
    } catch (IlvDiagrammerException e) {
      e.printStackTrace();
      System.exit(1);
    } catch (IOException e) {
      System.err.println("Could not read the file " + url);
      e.printStackTrace();
      System.exit(1);
    }
    // no need for scrollbars
    _dashboard.setScrollable(false);
    
    // display the diagram
    if (_isApplet) {
      getContentPane().add(_dashboard);
    } else {
      JFrame frame = new JFrame();
      frame.getContentPane().add(_dashboard);
      frame.setTitle(path);
      frame.setBounds(0, 0, 787, 558);
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      frame.setVisible(true);
    }
  }

  /**
   * Starts the application/applet.
   */
  public void start() {
    _animationThread = new Thread(this);
    _animationThread.start(); 
  }
  
  /**
   * Stops the applet.
   */
  public void stop() {
    _animationThread.interrupt();
  }
  
  
  /////////////////////////////////////////////////////////////////
  
  // called by the animation thread
  public void run() {
    while (true) {
      // animate the diagram
      changeRandomValues();
      // update GUI
      updateDashBoard(); // no need to invoke within a SwingUtilities.invokeAndWait()
      try {
        Thread.sleep(ANIM_DELAY);
      } catch (InterruptedException ex) {
        Thread.currentThread().interrupt();
        break;
      }
    }
  }

  /**
   * 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, by changing properties on the model.
  private void updateDashBoard() {
    _dashboard.setAdjusting(true);
    
    // update the 4 bar charts
    Object visitors = _dashboard.getObject("visitors");
    double totalVisitors = 0d;
    for (int i=0; i<4; i++) {
      _dashboard.setObjectProperty(visitors, 
          "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);
  }

}