/*
 * 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.Frame;
import java.awt.GridLayout;
import java.awt.Panel;
import java.awt.TextField;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;

import ilog.views.IlvGraphic;
import ilog.views.IlvManager;
import ilog.views.IlvManagerView;
import ilog.views.IlvPoint;
import ilog.views.awt.IlvScrollManagerView;
import ilog.views.event.ManagerSelectionChangedEvent;
import ilog.views.event.ManagerSelectionListener;
import ilog.views.graphic.IlvMarker;
import ilog.views.interactor.IlvSelectInteractor;
import ilog.views.maps.IlvMapInputStream;
import ilog.views.maps.projection.IlvBadProjectionParameter;
import ilog.views.maps.projection.IlvEllipsoid;
import ilog.views.maps.projection.IlvLambertAzimuthalEqualAreaProjection;
import ilog.views.maps.projection.IlvProjection;
import ilog.views.maps.projection.IlvProjectionException;
import ilog.views.maps.projection.IlvProjectionUtil;
import ilog.views.util.IlvProductUtil;

class ProjSample2 extends Frame {
  private IlvManager manager;
  private IlvManagerView mgrview;
  private IlvProjection projection;
  private TextField llField;
  private TextField cityField;

  public ProjSample2() {
    super("Integrating projections and graphics");

    // creation of the panel
    manager = new IlvManager();
    mgrview = new IlvManagerView(manager);
    IlvScrollManagerView panel = new IlvScrollManagerView(mgrview);
    setLayout(new BorderLayout());
    add("Center", panel);
    Panel southPanel = new Panel();
    southPanel.setLayout(new GridLayout(1, 0));
    llField = new TextField();
    llField.setEditable(false);
    southPanel.add(llField);
    cityField = new TextField();
    cityField.setEditable(false);
    southPanel.add(cityField);
    add("South", southPanel);

    // loading a map of the usa
    try {
      IlvMapInputStream mapInput = new IlvMapInputStream("../../../../data/maps/usa.ivl");
      mapInput.read(manager);
    } catch (Exception e) {
      e.printStackTrace();
      System.exit(0);
    }
    createProjection();
    addCities();
    setViewInteractor();
    mgrview.setKeepingAspectRatio(true);
    addWindowListener(new WindowAdapter() {
      Override
      public void windowClosing(WindowEvent evt) {
        System.exit(0);
      }

      Override
      public void windowOpened(WindowEvent evt) {
        mgrview.fitTransformerToContent();
      }
    });
    setSize(400, 300);
    setVisible(true);
  }

  /**
   * This function creates the projection to be used with the file usa.ivl
   */
  private void createProjection() {
    projection = new IlvLambertAzimuthalEqualAreaProjection();
    projection.setEllipsoid(IlvEllipsoid.SPHERE);
    try {
      double centralMeridian = IlvProjectionUtil.DMSToRadian("100DW");
      double centralParallel = IlvProjectionUtil.DMSToRadian("40DN");
      projection.setCentralMeridian(centralMeridian);
      projection.setCentralParallel(centralParallel);
    } catch (IlvBadProjectionParameter e) {
      System.out.println("wrong string passed to " + "IlvProjectionUtil.DMSToRadian");
      System.out.println("unable to create the projection for the file" + "usa.ivl");
      System.exit(0);
    }
  }

  /**
   * This function adds some cities on top of the map of the USA.
   */
  private void addCities() {
    addCity("Washington", "39D11'N", "76D51W");
    addCity("New York", "40D59'N", "73D39'W");
    addCity("Miami", "25D58'N", "80D02'W");
    addCity("San Francisco", "37D44'N", "122D20'W");
    addCity("Seattle", "47D51'N", "122D01'W");
    addCity("Denvers", "39D50'N", "104D53'W");
  }

  private void addCity(String cityName, String lat, String lon) {
    try {
      double latitude = IlvProjectionUtil.DMSToRadian(lat);
      double longitude = IlvProjectionUtil.DMSToRadian(lon);
      IlvPoint p = new IlvPoint(longitude, latitude);
      projection.forward(p);
      IlvProjectionUtil.invertY(p);
      IlvMarker marker = new IlvMarker(p, IlvMarker.IlvMarkerFilledDiamond);
      marker.setSize(4);
      marker.setForeground(Color.red);
      manager.addObject(marker, 1, false);
      marker.setName(cityName);
    } catch (IlvProjectionException e) {
      e.printStackTrace();
    }
  }

  private void setViewInteractor() {
    IlvSelectInteractor interactor = new IlvSelectInteractor();
    interactor.setDragAllowed(false);
    interactor.setEditionAllowed(false);
    interactor.setMoveAllowed(false);
    interactor.setMultipleSelectionMode(false);
    manager.setSelectable(0, false);
    mgrview.pushInteractor(interactor);

    // display the name of the city when a city is selected
    manager.addManagerSelectionListener(new ManagerSelectionListener() {
      Override
      public void selectionChanged(ManagerSelectionChangedEvent e) {
        IlvGraphic g = e.getGraphic();
        if (g == null)
          return;
        String name = g.getName();
        if (name != null)
          cityField.setText(name);
      }
    });

    // display the position of the mouse
    interactor.addMouseMotionListener(new MouseMotionAdapter() {
      Override
      public void mouseMoved(MouseEvent e) {
        try {
          IlvPoint p = projection.inverse(e);
          llField.setText(IlvProjectionUtil.RadianToDMS(p));
        } catch (IlvProjectionException ex) {
          System.out.println("Unable to inverse this point " + ex.getMessage());
        }
      }
    });
  }

  static public void main(String args[]) {
    // This sample uses JViews Maps features. When deploying an
    // application that includes this code, you need to be in possession
    // of a Perforce JViews Maps Deployment license.
    IlvProductUtil.DeploymentLicenseRequired(IlvProductUtil.JViews_Maps_Deployment);

    // Sun recommends that to put the entire GUI initialization into the
    // AWT thread
    javax.swing.SwingUtilities.invokeLater(new Runnable() {
      Override
      public void run() {
        new ProjSample2();
      }
    });
  }
}