/*
 * 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.
 */
package bpmn;

import java.awt.Container;
import java.awt.Image;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.ResourceBundle;

import javax.swing.Action;
import javax.swing.ImageIcon;
import javax.swing.JToolBar;

import ilog.views.bpmn.IlvBPMNFrame;
import ilog.views.bpmn.IlvBPMNSDMUtilitiesFactory;
import ilog.views.bpmn.IlvBPMNSelectInteractor;
import ilog.views.bpmn.IlvBPMNUtilities;
import ilog.views.diagrammer.IlvDiagrammer;
import ilog.views.diagrammer.IlvDiagrammerException;
import ilog.views.diagrammer.application.IlvDiagrammerAction;
import ilog.views.diagrammer.application.IlvDiagrammerMenu;
import ilog.views.diagrammer.application.IlvDiagrammerMenuBar;
import ilog.views.diagrammer.application.IlvDiagrammerPaletteAction;
import ilog.views.diagrammer.application.IlvDiagrammerPaletteBar;
import ilog.views.diagrammer.application.IlvDiagrammerPropertySheet;
import ilog.views.diagrammer.application.IlvDiagrammerStatusBar;
import ilog.views.sdm.interactor.IlvSDMCompositeSelectInteractor;
import ilog.views.util.IlvImageUtil;
import ilog.views.util.IlvProductUtil;
import ilog.views.util.swing.IlvSwingUtil;

/**
 * This example shows how to build a business process modeler
 * that uses the Business Process Modeling Notation.
 * <p>
 * The example is based on the predefined class
 * {@link IlvDiagrammerApplication}
 * supplied with the diagram component.
 */
public class BPMNModeler extends IlvBPMNFrame
{
  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);
  }

  // The resource bundle used to get localized messages for
  // this class.
  //
  private ResourceBundle bundle;
  
  /**
   * Creates a new process modeler.
   */
  public BPMNModeler()
  {
    super();

    // Load the property file.
    //
    bundle = ResourceBundle.getBundle("bpmn");

    // User CSS or default CSS
    String cssPath = getCSSPath();
    
    // Set default arguments.
    setDefaultArgs(new String[]{
      "-title", bundle.getString("BPMNModeler.FrameTitle"),
      "-tabbed",
      "-separatedPalettes",
      "-tree",
      "-psheet",
      "-edit",
      "-style", cssPath
    });
  }
  
  protected String getCSSPath() {
    try {
      String cssPath = "userbpmn/userbpmn.css";
      File file = new File(cssPath);
      if (file.canRead()) {
        return cssPath;
      }
    } catch (Exception e) {      
    }
    return IlvBPMNUtilities.class.getResource("bpmn.css").toExternalForm();
  }

  /** 
   * Creates a simple version of the status bar for this application.
   */
  Override
  protected IlvDiagrammerStatusBar createStatusBar() {
    return new IlvDiagrammerStatusBar(true);
  }

  /**
   * Initializes the application.
   * @param contentPane The panel in which the GUI will be created.
   */
  Override
  public void init(final Container contentPane)
  {
    super.init(contentPane);
    IlvDiagrammerMenuBar mbar = (IlvDiagrammerMenuBar) getJMenuBar();
    mbar.getOptionsMenu().addAction(IlvDiagrammerAction.resizing);
    removeAction(mbar.getFileMenu(), IlvDiagrammerAction.openStyleSheet);
    removeAction(mbar.getFileMenu(), IlvDiagrammerAction.refresh);
    removeAction(mbar.getOptionsMenu(), IlvDiagrammerAction.editing);
    getEditToolBar().removeAction(IlvDiagrammerAction.refresh);
    ((IlvDiagrammerAction.FileAction) IlvDiagrammerAction.saveAs).setSuffixes(new String[] {".xml"});
    ((IlvDiagrammerAction.FileAction) IlvDiagrammerAction.open).setSuffixes(new String[] {".xml"});    
  }
  
  /** 
   * Creates the frame of the application.
   * @see ilog.views.diagrammer.application.IlvDiagrammerApplication#createFrame()
   */
  Override
  public void initFrame() {
    super.initFrame();
    setSize(808, 634);
  }

  /**
   * Returns false, so the tool bars are not floatable.
   */
  Override
  public boolean isFloatable() {
    return false;
  }

  protected void removeAction(IlvDiagrammerMenu menu,
                              Action action)
  {
    int ndx = menu.indexOf(action);
    if (ndx != -1) {
        menu.remove(ndx);
        if (menu.getItemCount() > ndx) {
          if (menu.getItem(ndx) == null) {
            // The  item next to the removed item is a separator
            // and the previous item is also a separator, remove 
            // a separator.
            if (ndx == 0 || menu.getItem(ndx - 1) == null) {
              menu.remove(ndx);
            }
          }
        }
    }
  }

  Override
  protected JToolBar[] createPaletteToolBars()
          throws Exception
  {
    return new JToolBar[]{
      createPalette("activities.xml"),
      createPalette("starts.xml"),
      createPalette("intermediates.xml"),
      createPalette("ends.xml"),
      createPalette("gateways.xml"),
      createPalette("flows.xml"),
      createPalette("artifacts.xml"),
      createPalette("pools.xml")
    };
  }
  
  Override
  protected IlvDiagrammer createDiagrammer()
  {
    IlvDiagrammer diagrammer = super.createDiagrammer();
    diagrammer.getView().setUtilitiesFactory(new IlvBPMNSDMUtilitiesFactory(this));
    IlvSDMCompositeSelectInteractor selinter = new IlvBPMNSelectInteractor();
    selinter.setOpaqueMove(true);
    selinter.setOpaqueResize(true);
    diagrammer.setSelectInteractor(selinter);
    diagrammer.setStickyModes(false);
    diagrammer.setResizingAllowed(true);
    diagrammer.setMinimumZoom(0.2);
    return diagrammer;
  }

  private JToolBar createPalette(String filename)
          throws IOException, IlvDiagrammerException
  {
    URL url = IlvBPMNUtilities.class.getResource("palettes/" + filename);
    IlvDiagrammerPaletteBar tbar =  new IlvDiagrammerPaletteBar(url, getStyleSheetURL(), JToolBar.HORIZONTAL);
    // Change the icons if specified in the source objects.
    Action[] actions = tbar.getActions();

    String filePrefix = getActionPrefix(filename);
    
    for (int ndx = 0; ndx < actions.length; ndx++) {
      // Override the default icon, and descriptions created by
      // the  IlvDiagrammerPaletteAction
      if (actions[ndx] instanceof IlvDiagrammerPaletteAction) {
        IlvDiagrammerPaletteAction action = (IlvDiagrammerPaletteAction) actions[ndx];
        String prefix = filePrefix + action.getPaletteDiagrammer().getID(action.getPaletteObject()) + ".";
        // The icon
        try {
          String iconPath = getActionProperty(action, prefix, Action.SMALL_ICON);
          Image image = IlvImageUtil.getImageFromFile(IlvBPMNUtilities.class, iconPath);
          ImageIcon imageIcon = new ImageIcon(image);
          action.putValue(Action.SMALL_ICON, imageIcon);          
        } catch (Exception e) {          
        }
        // The short description
        setActionProperty(action, prefix, Action.SHORT_DESCRIPTION);
        // The long description
        setActionProperty(action, prefix, Action.LONG_DESCRIPTION);
      }
    }
    return tbar;
  }
  
  private static String getActionPrefix(String filename) {
    String result = "BPMNModeler.Palette.";
    // Add the file name.
    int index = filename.indexOf('.');
    if (index != -1) {
      // Only use the file name part.
      result += filename.substring(0, index);
    } else {
      result += filename;
    }
    result += ".";
    return result;
  }
  
  private String getActionProperty(IlvDiagrammerAction action, String prefix, String key) {
    try {
      return bundle.getString(prefix + key);
    } catch (Exception e) {
      return null;
    }
  }
  
  private void setActionProperty(IlvDiagrammerPaletteAction action, String prefix, String key) {
    String str = getActionProperty(action, prefix, key);
    if (str != null) {
      action.putValue(key, str);
    }
  }
  
  private static void globalInit() {
    IlvDiagrammerPropertySheet.allowUserDefinedType(false);
    IlvDiagrammerAction.about.putValue(IlvDiagrammerAction.ABOUT_APPLICATION_NAME, "BPMN Modeler");    
  }

  /**
   * The main method of the application. You must always supply your
   * own main when subclassing
   * {@link IlvDiagrammerApplication}.
   * @param args The command-line arguments.
   */
  public static void main(final String[] args)
  {
    globalInit();
    // Create the new modeler application and show it.
    IlvSwingUtil.invokeLater(new Runnable() {
      Override
      public void run() {
        new BPMNModeler().init(args);
      }
    });
  }
}