/*
 * 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.io.IOException;
import java.net.URL;

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

import ilog.views.dashboard.IlvDashboardContext;
import ilog.views.dashboard.IlvDashboardDiagram;
import ilog.views.diagrammer.IlvDiagrammerException;
import ilog.views.util.swing.IlvSwingUtil;


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

  /**
   * 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() {
        BAMCockpit dashboard = new BAMCockpit();
        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;

  /**
   * Creates the BAM dashboard.
   */
  public BAMCockpit() {}

  /**
   * Initializes app.
   */
  public void init() {
    IlvSwingUtil.invokeAndWait(new Runnable() {
      Override
      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 {
      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
    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 animation.
   */
  public void start() {
    _animationThread = new Thread(this);
    _animationThread.start();
  }

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


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

  // called by the animation thread
  Override
  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), Double.valueOf(_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", Double.valueOf(total / 1000d));
    _dashboard.setObjectProperty(yty1, "preset", Double.valueOf((Math.random() - 0.5) + total / 1000d));

    // update funnel1
    Object f1 = _dashboard.getObject("website");
    total = (int) totalVisitors * 550;
    _dashboard.setObjectProperty(f1, "value1", Integer.valueOf(total));
    _dashboard.setObjectProperty(f1, "value2", Integer.valueOf(total / 4));
    _dashboard.setObjectProperty(f1, "value3", Integer.valueOf(total / 5));
    _dashboard.setObjectProperty(f1, "value4", Integer.valueOf(total / 50));

    // update opportunities
    Object o1 = _dashboard.getObject("opportunities");
    total = (int) totalVisitors;
    _dashboard.setObjectProperty(o1, "value1", Integer.valueOf(total));
    _dashboard.setObjectProperty(o1, "value2", Integer.valueOf(total / 4));
    _dashboard.setObjectProperty(o1, "value3", Integer.valueOf(total / 5));
    _dashboard.setObjectProperty(o1, "value4", Integer.valueOf(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", Integer.valueOf(val));
    _dashboard.setObjectProperty(yty2, "preset", Double.valueOf((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", Double.valueOf(rev_value * 3 + Math.random() * 50));
    _dashboard.setObjectProperty(revenues, "Europe",
        Double.valueOf(rev_value * 2 + Math.random() * 50));
    _dashboard.setObjectProperty(revenues, "APAC", Double.valueOf(rev_value * 1 + Math.random() * 50));
    _dashboard.setObjectProperty(revenues, "ROW", Double.valueOf(rev_value * 1 + Math.random() * 50));

    _dashboard.setAdjusting(false);
  }

}