/*
 * 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.IlvPoint;
import ilog.views.diagrammer.IlvDiagrammer;
import ilog.views.diagrammer.project.IlvDiagrammerProject;
import ilog.views.maps.IlvCoordinateSystemProperty;
import ilog.views.maps.IlvMapScaleLimiter;
import ilog.views.maps.beans.IlvJAreaOfInterestPanel;
import ilog.views.maps.beans.IlvJMapsManagerViewControlBar;
import ilog.views.maps.beans.IlvJMouseCoordinateViewer;
import ilog.views.maps.beans.IlvMapLegend;
import ilog.views.maps.projection.IlvProjectionUtil;
import ilog.views.maps.srs.coordsys.IlvGeographicCoordinateSystem;
import ilog.views.sdm.IlvSDMModel;
import ilog.views.sdm.model.IlvSDMNode;
import ilog.views.util.IlvProductUtil;
import java.awt.BorderLayout;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionListener;
import java.io.File;
import java.net.URL;
import java.util.Enumeration;
import javax.swing.JApplet;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.Timer;

/**
 * This sample is a very simple mapping application that displays a diagram
 * stored in an IDPR file, built using the "Designer".
 * 
 * @since JViews 7.0
 */
public class LoadDiagDemo extends JApplet {
  private static final class SymbolMouseListener extends MouseAdapter implements MouseMotionListener {
    private IlvDiagrammer diagrammer;
    private Cursor defaultCursor = Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR);
    private Cursor handCursor = Cursor.getPredefinedCursor(Cursor.HAND_CURSOR);
    SymbolMouseListener(IlvDiagrammer diagrammer) {
      this.diagrammer = diagrammer;
    }
    // display a dialog.
    public void mouseClicked(MouseEvent e) {
      if (e.getClickCount() >= 2) {
        Object target = diagrammer.getEngine().getObject(new IlvPoint(e.getX(), e.getY()), diagrammer.getView());
        if (target instanceof IlvSDMNode) {
          IlvSDMNode node = (IlvSDMNode) target;
          String properties[] = node.getPropertyNames();
          Object columnNames[] = { "Property", "Value" }; //$NON-NLS-1$ //$NON-NLS-2$
          Object rowData[][] = new Object[properties.length][2];
          for (int i = 0; i < rowData.length; i++) {
            rowData[i][0] = properties[i];
            rowData[i][1] = node.getProperty(properties[i]);
          }
          JTable sheet = new JTable(rowData, columnNames);
          sheet.setEnabled(false);
          sheet.setPreferredScrollableViewportSize(sheet.getPreferredSize());
          JScrollPane pane = new JScrollPane(sheet);
          JOptionPane.showMessageDialog(diagrammer, pane, "Symbol information", JOptionPane.INFORMATION_MESSAGE); //$NON-NLS-1$
        }
      }
    }
    public void mouseDragged(MouseEvent e) {
      // ignore
    }
    public void mouseMoved(MouseEvent e) {
      // change the cursor if mouse moves over a node
      Object target = diagrammer.getEngine().getObject(new IlvPoint(e.getX(), e.getY()), diagrammer.getView());
      if (target instanceof IlvSDMNode) {
        if (diagrammer.getView().getCursor() != handCursor) {
          defaultCursor = diagrammer.getView().getCursor();
          diagrammer.getView().setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
        }
      } else if (diagrammer.getView().getCursor() == handCursor) {
        diagrammer.getView().setCursor(defaultCursor);
      }
    }
  }
  {
    // This sample uses JViews Maps features. When deploying an
    // application that includes this code, you need to be in possession
    // of a JViews Maps Deployment license.
    IlvProductUtil.DeploymentLicenseRequired(
        IlvProductUtil.JViews_Maps_Deployment);
  }
  // mouse coordinate information bean
  IlvJMouseCoordinateViewer locator = new IlvJMouseCoordinateViewer();
  // Map legend bean
  IlvMapLegend legend = new IlvMapLegend();
  IlvDiagrammer diagrammer = new IlvDiagrammer();
  // zoom & selection toolbar
  IlvJMapsManagerViewControlBar viewToolbar = new IlvJMapsManagerViewControlBar();
  IlvJAreaOfInterestPanel aoipanel;
  int step = 0;// animation count
  /**
   * Creates a frame containing the different map beans.
   */
  public LoadDiagDemo() {
    super();
    // Make sure the swing construction is called in Swing event thread.
    ilog.views.util.swing.IlvSwingUtil.invokeAndWait(new Runnable() { public void run() {
    // Setup the beans
    locator.setView(diagrammer.getView());
    legend.setView(diagrammer.getView());
    viewToolbar.setView(diagrammer.getView());
    aoipanel = new IlvJAreaOfInterestPanel(diagrammer.getView(), true, true, true);
    diagrammer.getView().setSize(new Dimension(900, 450));
    // geo reference the view
    diagrammer.getEngine().getGrapher().setNamedProperty(new IlvCoordinateSystemProperty(IlvGeographicCoordinateSystem.WGS84));
    // limit the zoom to correct scales.
    IlvMapScaleLimiter limiter = new IlvMapScaleLimiter((float) (1 / 1E5), (float) (1 / 1E8));
    limiter.setView(diagrammer.getView());
    // arrange the main window
    getContentPane().add(viewToolbar, BorderLayout.NORTH);
    getContentPane().add(diagrammer, BorderLayout.CENTER);
    JPanel status = new JPanel(new BorderLayout());
    status.add(locator, BorderLayout.LINE_START);
    getContentPane().add(status, BorderLayout.SOUTH);
    getContentPane().add(legend, BorderLayout.LINE_END);
    getContentPane().add(aoipanel, BorderLayout.LINE_START);
    /* to load the initial file */
    loadFile("data/world.idpr"); //$NON-NLS-1$
    /* --- End of Load diag GUI --- */
    // timer to change the model every 2 second.
    Timer timer = new Timer(2000,new ActionListener() {
      public void actionPerformed(ActionEvent e) {
        IlvSDMModel model = diagrammer.getEngine().getModel();
        Enumeration objs = diagrammer.getEngine().getAllObjects();
        while (objs.hasMoreElements()) {
          Object obj = objs.nextElement();
          if(true){
          // retrieve (and possibly store in the model) the center point of the animation.
          Object olat = model.getObjectProperty(obj, "latitude0"); //$NON-NLS-1$
          if (olat == null) {
            olat = model.getObjectProperty(obj, "latitude"); //$NON-NLS-1$
            model.setObjectProperty(obj, "latitude0", olat); //$NON-NLS-1$
          }
          Object olon = model.getObjectProperty(obj, "longitude0"); //$NON-NLS-1$
          if (olon == null) {
            olon = model.getObjectProperty(obj, "longitude"); //$NON-NLS-1$
            model.setObjectProperty(obj, "longitude0", olon); //$NON-NLS-1$
          }
          // store some fake speed if it does not exist in model
          Object ospeed = model.getObjectProperty(obj, "speed"); //$NON-NLS-1$
          double speed;
          if (ospeed == null) {
            speed =  Math.random()*Math.PI/10;
            model.setObjectProperty(obj, "speed", "" + speed); //$NON-NLS-1$ //$NON-NLS-2$
          } else {
            speed = Double.parseDouble(ospeed.toString());
          }
          double range = Math.toRadians(0.5);// roaming range for objects.
          Object otype = model.getObjectProperty(obj, "type"); //$NON-NLS-1$
          // improvement JV-1508
          if(otype!=null){
            int t=Integer.parseInt(otype.toString());
            switch(t){
            case 1:// plane
              break;
            case 2: // bus
            case 3: // car
              range=range/10.0;// smaller range
              break;
            case 4: // boat
              range=range/5.0;// smaller range
              break;
            }
          }
          try {
            double lat0 = IlvProjectionUtil.DMSToRadian(olat.toString());
            double lon0 = IlvProjectionUtil.DMSToRadian(olon.toString());
            double lon = lon0 + range * Math.cos(step * speed );
            double lat = lat0 + range * Math.sin(step * speed );
            model.setObjectProperty(obj, "latitude", "" + IlvProjectionUtil.RadianToDMS(lat, true)); //$NON-NLS-1$ //$NON-NLS-2$
            model.setObjectProperty(obj, "longitude", "" + IlvProjectionUtil.RadianToDMS(lon, false)); //$NON-NLS-1$ //$NON-NLS-2$
          } catch (Exception ex) {
            // badly formed lat/lon - ignore that.
          }
          }
        }
        step++;
      }
    });
    timer.start();
    // add a listener to display an information dialog on double click.
    SymbolMouseListener listener = new SymbolMouseListener(diagrammer);
    diagrammer.getView().addMouseListener(listener);
    diagrammer.getView().addMouseMotionListener(listener);
    }});
  }
  /**
   * Load a file into the view's manager.
   * 
   * @param idprFile
   *          prebuilt file to read.
   */
  public void loadFile(final String idprFile) {
    try {
      /*
       * if the palette is not in the classpath, here is the code to load the
       * palette, in a non pure applet context: try { IlvPaletteManager
       * paletteManager=new IlvPaletteManager();
       * paletteManager.load(findURL("data/transportationServices.jar"));
       * //$NON-NLS-1$ paletteManager.attach(diagrammer.getEngine()); } catch
       * (Throwable t){ System.out.println("Cannot load the palette, expecting
       * it to be in the CLASSPATH "); //$NON-NLS-1$ t.printStackTrace(); //
       * ignore; }
       */
      // Load the idpr file
      IlvDiagrammerProject project = new IlvDiagrammerProject(findURL(idprFile));
      diagrammer.setProject(project);
      diagrammer.fitToContents();
    } catch (Exception ex) {
      ex.printStackTrace();
    }
  }
  private static URL findURL(String resource) {
    URL rtnURL = null;
    boolean exists;
    try {
      exists = new File(resource).exists();
    } catch (SecurityException e) {
      // applet
      exists = false;
    }
    if (exists) {
      try {
        rtnURL = new File(resource).toURI().toURL();
      } catch (Exception e) {
        e.printStackTrace();
      }
    } else {
      rtnURL = LoadDiagDemo.class.getResource(resource);
      if (rtnURL == null) {
        rtnURL = LoadDiagDemo.class.getResource("/" + resource); //$NON-NLS-1$
      }
    }
    return rtnURL;
  }
  /**
   * Main method
   * 
   * @param args
   *          (ignored)
   */
  public static void main(String[] args) {
    // Sun recommends that to put the entire GUI initialization into the
    // AWT thread
    javax.swing.SwingUtilities.invokeLater(
      new Runnable() {
        public void run() {
          final JFrame frame = new JFrame();
          // Make sure the application will exit when we close its window.
          frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
          LoadDiagDemo applet = new LoadDiagDemo();
          frame.getContentPane().add(applet);
          frame.setTitle("Diagrammer Project Loading Demo"); //$NON-NLS-1$ 
          // This could be externalized in a resources/messages.properties file using
          // IlvMapUtil.getString call.
          frame.pack();
          frame.setVisible(true);
        }
      }
      );
  }
  //JV-3814
  Override
  public void destroy() { 
    super.destroy(); 
    // This method is intended to workaround memory management issues 
    // in the Sun JRE. Please refer to the method documentation for more 
    // details and a description of the known issues. 
    ilog.views.util.swing.IlvSwingUtil.cleanupApplet(); 
  } 
}