/*
 * 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.Color;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.GradientPaint;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.net.URL;

import javax.swing.AbstractAction;
import javax.swing.AbstractButton;
import javax.swing.Action;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JRootPane;
import javax.swing.JSlider;
import javax.swing.SwingConstants;
import javax.swing.SwingUtilities;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

import ilog.views.IlvManager;
import ilog.views.diagrammer.IlvDiagrammer;
import ilog.views.diagrammer.application.IlvDiagrammerToolBar;
import ilog.views.util.IlvProductUtil;

/**
 * This is a simple application based on a diagram component,
 * {@link ilog.views.diagrammer.IlvDiagrammer}. It shows little objects turning
 * around a central object, and changing some of their properties according to
 * their position or status.
 */
public class CustomGraphics extends JRootPane {

  /**
   * Controls whether using CSS version or not. Default is true. Note that the
   * application produces the same result whatever the value.
   */
  public final static boolean USE_CSS = true;

  /**
   * The width of the view in the diagrammer.
   */
  public static final int VIEW_WIDTH = 800;
  /**
   * The height of the view in the diagrammer.
   */
  public static final int VIEW_HEIGHT = 600;

  /**
   * The instance of the diagrammer.
   */
  private IlvDiagrammer diagrammer;

  /**
   * The instance of the simulator.
   */
  private Simulator simulator;

  /**
   * Create the main frame.
   *
   * @throws Exception
   *           if an error occurs for any reason.
   */
  public void init(Container contentPane) throws Exception {
    // 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);

    // Create the IlvDiagrammer instance.
    diagrammer = new IlvDiagrammer();
    diagrammer.setPreferredSize(new Dimension(VIEW_WIDTH, VIEW_HEIGHT));

    // Disallow selection.
    diagrammer.setSelectMode(false);

    // Add the IlvDiagrammer instance to the frame.
    contentPane.setLayout(new BorderLayout());
    contentPane.add(diagrammer, BorderLayout.CENTER);

    // Create the actions to start and stop the simulator.
    Action resetSimulator = new ResetSimulatorAction();
    Action startSimulator = new PlaySimulatorAction();
    Action stopSimulator = new PauseSimulatorAction();

    // These are the actions that will go in the toolbar.
    Action[] actions = { resetSimulator, startSimulator, stopSimulator };

    // Create the simulator. If 2nd parameter is
    // - true: use CSS
    // - false: don't use CSS
    simulator = new Simulator(diagrammer, USE_CSS);

    // Set triple buffering for the background in layer 1.
    diagrammer.getView().setTripleBufferedLayerCount(1);

    // set background graphic
    final IlvManager manager = diagrammer.getView().getManager();
    manager.read(getClass().getResource("zones.ivl"));

    // Add a toolbar for controlling the application at the north of the frame.
    // this toolbar is a little bit customized to get a nicer look ;-)
    IlvDiagrammerToolBar toolbar = new IlvDiagrammerToolBar(actions, SwingConstants.HORIZONTAL) {

      private GradientPaint paint = null;
      private Insets insets = new Insets(0, 0, 0, 0);

      Override
      public AbstractButton addAction(Action action) {
        AbstractButton b = super.addAction(action);
        b.setContentAreaFilled(false);
        b.setBorderPainted(false);
        b.setMargin(insets);
        b.setOpaque(false);

        URL iconUpURL = null, iconDownURL = null;

        if (action instanceof PlaySimulatorAction) {
          iconUpURL = this.getClass().getResource("play_up.gif");
          iconDownURL = this.getClass().getResource("play_down.gif");
        } else if (action instanceof PauseSimulatorAction) {
          iconUpURL = this.getClass().getResource("pause_up.gif");
          iconDownURL = this.getClass().getResource("pause_down.gif");
        } else if (action instanceof ResetSimulatorAction) {
          iconUpURL = this.getClass().getResource("reset_up.gif");
          iconDownURL = this.getClass().getResource("reset_down.gif");
        }
        if (iconUpURL != null) {
          b.setIcon(new ImageIcon(iconUpURL));
        }
        if (iconDownURL != null) {
          b.setPressedIcon(new ImageIcon(iconDownURL));
        }

        return b;
      }

      Override
      public void paintComponent(Graphics g) {
        if (paint == null)
          paint = new GradientPaint(0, 0, new Color(34, 34, 34), 0, getHeight(), new Color(83, 83, 83));
        Graphics2D g2 = (Graphics2D) g;
        g2.setPaint(paint);
        g2.fillRect(0, 0, getWidth(), getHeight());

      }
    };
    toolbar.setFloatable(false);
    contentPane.add(toolbar, BorderLayout.NORTH);

    // Add a slider in the toolbar to change animation speed of the simulator
    final JSlider slider = new JSlider(1, 10);
    slider.setOpaque(false);
    slider.setValue(1);
    slider.addChangeListener(new ChangeListener() {
      Override
      public void stateChanged(ChangeEvent e) {
        simulator.setSpeedAccelerator(slider.getValue());
      }
    });
    toolbar.add(slider);

    // Fill the view with a random model once everything has been realized.
    SwingUtilities.invokeLater(new Runnable() {
      /**
       * Create a random model.
       */
      Override
      public final void run() {
        manager.setFillOn(true);
        manager.setBackground(Color.black);

        // create the model that will be simulated and animated
        simulator.createRandomModel();
      }
    });
  }

  public void stop() {
    // Stop simulator
    System.out.println("stopping simulator...");
    simulator.stop();
  }

  
  /**
   * The main method of the application.
   *
   * @param args
   *          the command line arguments for the application (these arguments
   *          are ignored by this application).
   */
  public static void main(final String[] args) {
    javax.swing.SwingUtilities.invokeLater(new Runnable() {
      Override
      public void run() {
        // Create an instance of the application, and show it.
        try {
          CustomGraphics app = new CustomGraphics();
          JFrame frame = new JFrame("Creating Custom Graphics using the SDK");
          app.init(frame.getContentPane());
          frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
          frame.setLocation(100, 100);
          frame.pack();
          frame.setVisible(true);
        } catch (Exception e) {
          e.printStackTrace(System.err);
        }
      }
    });
  }

  /**
   * This is the action to start the simulator.
   */
  private final class PlaySimulatorAction extends AbstractAction {
    /**
     * Create an instance of the action to start the simulator.
     */
    public PlaySimulatorAction() {
      super("Start");
      setEnabled(true);
      putValue(Action.SHORT_DESCRIPTION, "Start the simulator");
    }

    /**
     * Stop the simulator.
     *
     * @param e
     *          the {@link ActionEvent ActionEvent} for this action.
     */
    Override
    public void actionPerformed(final ActionEvent e) {
      simulator.start();
    }
  }

  /**
   * This is the action to stop the simulator.
   */
  private final class PauseSimulatorAction extends AbstractAction {
    /**
     * Create an instance of the action to stop the simulator.
     */
    public PauseSimulatorAction() {
      super("Stop");
      putValue(Action.SHORT_DESCRIPTION, "Stop the simulator");
    }

    /**
     * Stop the simulator.
     *
     * @param e
     *          the {@link ActionEvent ActionEvent} for this action.
     */
    Override
    public void actionPerformed(final ActionEvent e) {
      simulator.stop();
    }
  }

  /**
   * This is the action to stop the simulator.
   */
  private final class ResetSimulatorAction extends AbstractAction {
    /**
     * Create an instance of the action to stop the simulator.
     */
    public ResetSimulatorAction() {
      super("Reset");
      putValue(Action.SHORT_DESCRIPTION, "Reset simulator");
    }

    /**
     * Stop the simulator.
     *
     * @param e
     *          the {@link ActionEvent ActionEvent} for this action.
     */
    Override
    public void actionPerformed(final ActionEvent e) {
      simulator.reset();
    }
  }
}