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

import java.awt.BorderLayout;
import java.awt.Container;
import java.net.URL;
import java.util.Iterator;

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


/**
 * This is the entry point of the ManyGauges demo. 
 */
public class ManyGauges 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() {
          ManyGauges dashboard = new ManyGauges();
          dashboard._isApplet = false; 
          dashboard.init();
          dashboard.start();
        }});
  }


  // delay between refreshes, in ms
  public  long ANIM_DELAY = 20l; // real time: try 0l

  private IlvDashboardDiagram _dashboard;
  private Thread _animationThread;
  private boolean _isApplet = true;

  /**
   * Default Constructor.
   */
  public ManyGauges() {
  }

  /**
   * Initializes the application/applet.
   */
  public void init() {
    IlvSwingUtil.invokeAndWait(new Runnable() { 
      public void run() { 
        createGUI(); 
      } 
    });     
  }
  
  private void createGUI() {
    // the path to the dashboard file (which defines the dashboard)
    String path = "data/manyGauges.idbin";

    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.readBinary(url);
    } catch (IlvDashboardException er) {
      er.printStackTrace();
      System.exit(-1);
    } catch (Exception e) {
      System.err.println("Could not read the file " + url);
      System.exit(-1);
    }
    // no need for scrollbars
    _dashboard.setScrollable(true);

    if (_isApplet) {
      Container container = getContentPane();
      container.setLayout(new BorderLayout(2, 2));
      container.add(_dashboard);
      container.add(new IlvDiagrammerViewBar(), BorderLayout.NORTH);
    } else {
      JFrame frame = new JFrame();
      Container container = frame.getContentPane();
      container.setLayout(new BorderLayout(2, 2));
      container.add(_dashboard);
      container.add(new IlvDiagrammerViewBar(), BorderLayout.NORTH);
      frame.setTitle("Performance with Many Gauges");
      frame.setBounds(0, 0, 787, 558);
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      frame.setVisible(true);
    }
  
  }

  /**
   * Starts the application/applet.
   */
  public void start() {
    InitializeObjects();
    _animationThread = new Thread(this);
    _animationThread.start(); 
  }

  /**
   * Stops the applet.
   */
  public void stop() {
    _animationThread.interrupt();
  }

  /**
   * Set a default value for each object. Only once, at the beginning
   */  
  void InitializeObjects() {
    int i = 1;
    Object symbol = null;
    Iterator it = _dashboard.getObjects();
    while(it.hasNext()) {
      symbol = it.next();
      Double db = new Double(Math.random() * 100);
      // Initialize with random value
      _dashboard.setObjectProperty(symbol, "value", db);
      // A label for each symbol
      _dashboard.setObjectProperty(symbol, "name", "Symbol # "+i++);
    }    
  }

  /////////////////////////////////////////////////////////////////

  // called by the animation thread
  public void run() {
    while (true) {
      // 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() {
    Object symbol = null;
    Iterator it = _dashboard.getObjects();
    while(it.hasNext()) {
      symbol = it.next();
      // Do not change all objects
      if (Math.random() < 0.2)
      {
        // Compute new value by adding a random value to the current one.
        Double db = (Double) _dashboard.getObjectProperty(symbol, "value");
        db = db + Math.random() * 30;
        if (db > 100) db = 0d;
        // Set value
        _dashboard.setObjectProperty(symbol, "value", db);
      }

    }    
  }


  // update the dashboard symbols, by changing properties on the model.
  private void updateDashBoard() {
    _dashboard.setAdjusting(true);
    try {
      changeRandomValues();  
    } finally {
      _dashboard.setAdjusting(false);
    }
  }

}