/*
 * Licensed Materials - Property of Perforce Software, Inc. 
 * © Copyright Perforce Software, Inc. 2014, 2021 
 * © 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 java.awt.BorderLayout;
import java.awt.Container;
import java.net.URL;
import java.util.Iterator;

import javax.swing.JFrame;
import javax.swing.JRootPane;

import ilog.views.dashboard.IlvDashboardContext;
import ilog.views.dashboard.IlvDashboardDiagram;
import ilog.views.dashboard.IlvDashboardException;
import ilog.views.diagrammer.application.IlvDiagrammerViewBar;
import ilog.views.util.IlvProductUtil;
import ilog.views.util.swing.IlvSwingUtil;


/**
 * This is the entry point of the ManyGauges demo. 
 */
public class ManyGauges extends JRootPane implements Runnable {

  static {
    // This sample uses JViews Diagrammer features. When deploying an
    // application that includes this code, you need to be in possession
    // of a Perforce 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() {
      Override
      public void run() {
        ManyGauges dashboard = new ManyGauges();
        dashboard.init();
        dashboard.start();
      }
    });
  }


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

  private IlvDashboardDiagram _dashboard;
  private Thread _animationThread;

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

  /**
   * Initializes the application.
   */
  public void init() {
    IlvSwingUtil.invokeAndWait(new Runnable() {
      Override
      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);
    try {
      URL 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 " + e.getMessage());
      System.exit(-1);
    }
    // no need for scrollbars
    _dashboard.setScrollable(true);

    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.
   */
  public void start() {
    InitializeObjects();
    _animationThread = new Thread(this);
    _animationThread.start();
  }

  /**
   * Stops the application.
   */
  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 = Double.valueOf(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
  Override
  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);
    }
  }

}