/*
 * 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 ilog.views.IlvGrapher;
import ilog.views.IlvManagerView;
import ilog.views.maps.IlvCoordinate;
import ilog.views.maps.IlvCoordinateSystemProperty;
import ilog.views.maps.IlvMapLayerTreeProperty;
import ilog.views.maps.IlvMapScaleLimiter;
import ilog.views.maps.beans.IlvJMapsManagerViewControlBar;
import ilog.views.maps.beans.IlvJMouseCoordinateViewer;
import ilog.views.maps.beans.IlvLayerTreePanel;
import ilog.views.maps.beans.IlvMapLayer;
import ilog.views.maps.beans.IlvMapLayerTreeModel;
import ilog.views.maps.datasource.IlvGraphicLayerDataSource;
import ilog.views.maps.datasource.IlvMapDataSourceModel;
import ilog.views.maps.datasource.IlvMapDataSourceProperty;
import ilog.views.maps.defense.terrain.IlvAltitudeVisibilityChart;
import ilog.views.maps.defense.terrain.IlvComputedRasterReader;
import ilog.views.maps.defense.terrain.IlvGradientRasterStyle;
import ilog.views.maps.defense.terrain.IlvImageComputation;
import ilog.views.maps.defense.terrain.IlvLineOfVisibility;
import ilog.views.maps.defense.terrain.IlvLineOfVisibilityStyle;
import ilog.views.maps.format.dted.IlvRasterDTEDReader;
import ilog.views.maps.graphic.IlvMapSelectionFactory;
import ilog.views.maps.raster.datasource.IlvRasterDataSourceFactory;
import ilog.views.maps.raster.datasource.IlvTiledRasterDataSource;
import ilog.views.maps.srs.coordsys.IlvGeographicCoordinateSystem;
import ilog.views.swing.IlvThreadedActivityMonitor;
import ilog.views.swing.IlvThreadedActivityMonitorPanel;
import ilog.views.swing.IlvThreadedActivityMonitorProperty;
import ilog.views.util.IlvProductUtil;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.geom.Rectangle2D;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JRootPane;

/**
 * Demo that shows the loading of DTED files using JVIews Maps API.
 */
SuppressWarnings("serial")
public class TerrainDemo extends JRootPane {

  {
    // This sample uses JViews Maps for Defense features. When deploying an
    // application that includes this code, you need to be in possession
    // of a Perforce JViews Maps for Defense Deployment license.
    IlvProductUtil.DeploymentLicenseRequired(
        IlvProductUtil.JViews_Maps_for_Defense_Deployment);
  }

  IlvManagerView view = new IlvManagerView(new IlvGrapher());
  IlvMapDataSourceModel dataSourceModel = IlvMapDataSourceProperty.GetMapDataSourceModel(view.getManager());
  IlvMapLayerTreeModel ltm = IlvMapLayerTreeProperty.GetMapLayerTreeModel(view.getManager());
  IlvThreadedActivityMonitor mon = IlvThreadedActivityMonitorProperty.GetThreadedActivityMonitor(view.getManager());
  IlvThreadedActivityMonitorPanel threadPanel = new IlvThreadedActivityMonitorPanel(mon);

  /**
   * Creates a terrain analysis demo in an applet context.
   */
  public TerrainDemo() {
    super();
    // Make sure the swing construction is called in Swing event thread.
    ilog.views.util.swing.IlvSwingUtil.invokeAndWait(new Runnable() { Override
    public void run() {
    // create the main components
    IlvLayerTreePanel layerTreePanel = new IlvLayerTreePanel();
    layerTreePanel.setView(view);
    IlvJMapsManagerViewControlBar viewToolbar = new IlvJMapsManagerViewControlBar();
    viewToolbar.setView(view);
    IlvJMouseCoordinateViewer locator = new IlvJMouseCoordinateViewer();
    locator.setView(view);
    view.setKeepingAspectRatio(true);
    view.setBackground(new Color(80, 180, 240));
    view.setSize(new Dimension(300, 600));

    // JV-2857 prevent editing/moving around map assets
    view.getManager().setSelectionFactory(new IlvMapSelectionFactory());
    // geo reference the view
    view.getManager().setNamedProperty(new IlvCoordinateSystemProperty(IlvGeographicCoordinateSystem.WGS84));
    // limit the zoom to correct scales.
    IlvMapScaleLimiter limiter = new IlvMapScaleLimiter((float) (1 / 1E4), (float) (1 / 1E7));
    limiter.setView(view);

    // Load some altitude data
//  loadFiles(new String[] { findURL("data/n36.dt0").getPath(),
//  findURL("data/n35.dt0").getPath()});
    loadFiles(new URL[] { findURL("data/n36.dt0"), //$NON-NLS-1$
        findURL("data/n35.dt0")});//$NON-NLS-1$
    computeRaster();
    makeLineOfSight();
    // select the dted layer.
    layerTreePanel.getLayerTree().setSelectionRow(0);
    JPanel southPanel = new JPanel(new BorderLayout());
    southPanel.add(locator, BorderLayout.WEST);
    southPanel.add(threadPanel, BorderLayout.EAST);
    // configure the main window
    getContentPane().add(viewToolbar, BorderLayout.NORTH);
    getContentPane().add(view, BorderLayout.CENTER);
    getContentPane().add(layerTreePanel, BorderLayout.LINE_START);
    getContentPane().add(southPanel, BorderLayout.SOUTH);
    }}); // event thread runnable
  }
 
  /**
   * Creates a DTED datasource from the specified URLs.
   */
  private void loadFiles(URL[] urls) {
    // create a raster reader for the dted file (necessary to create a datasource below)
    IlvRasterDTEDReader DTEDReader = new IlvRasterDTEDReader();
    // add dted files to the DTED reader
    for (int i = 0; i < urls.length; i++) {
      try {
        DTEDReader.addMap(urls[i]);
      } catch (IOException e) {
        e.printStackTrace();
      }
    }
    doLoadFiles(DTEDReader);
  }
  
  void doLoadFiles(IlvRasterDTEDReader DTEDReader) {
    // create a datasource for the dted reader (note that we do not use multithread here, to get the altitude provider working for the "analysis" method called immediately after).
    IlvTiledRasterDataSource DTEDDataSource = IlvRasterDataSourceFactory.buildTiledImageDataSource(view.getManager(), DTEDReader, false, false, null);
    DTEDDataSource.setName("DTED");//$NON-NLS-1$
    // insert it in the manager's data source tree 
    dataSourceModel.insert(DTEDDataSource);
    DTEDDataSource.start();
    // get the DTED  maplayer used to display that data source
    IlvMapLayer DTEDLayer = DTEDDataSource.getInsertionLayer();
    DTEDLayer.setName("DTED layer");//$NON-NLS-1$
    // insert it on the manager's map layer tree
    ltm.addChild(null, DTEDLayer);
    view.fitTransformerToContent();
  }

  /**
   * Creates a demo raster computation.
   */
  private void computeRaster() {
    IlvComputedRasterReader reader = new IlvComputedRasterReader(view.getManager());
    IlvImageComputation myComputation = new DemoAltitudeComputation();
    reader.setImageComputation(myComputation);
    IlvGradientRasterStyle style = new DemoRasterStyle(reader);
    style.setBounds(new Rectangle2D.Double(Math.toRadians(1), Math.toRadians(35.01), Math.toRadians(1), Math.toRadians(2)));
    style.setAlpha(0.5f);
    IlvTiledRasterDataSource ds = IlvRasterDataSourceFactory.buildTiledImageDataSource(view.getManager(), reader, true, false, null);
    reader.setStyle(style);
    dataSourceModel.insert(ds);
    ds.setName("Raster Computation");//$NON-NLS-1$
    // get the map layer used to display that data source
    IlvMapLayer rasterLayer = ds.getInsertionLayer();
    rasterLayer.setStyleControl(myComputation);
    rasterLayer.setName("Raster Computation layer");//$NON-NLS-1$
    rasterLayer.setStyle(style);
    // insert it on the manager's map layer tree
    ltm.addChild(null, rasterLayer);
    ds.start();
  }

  private void makeLineOfSight() {
    IlvLineOfVisibilityStyle style = new IlvLineOfVisibilityStyle();
    IlvLineOfVisibility lov = new DemoLineOfVisibility(view.getManager(), style.getPointOfViewHeight(), style.getPrecision(), new IlvCoordinate(Math.toRadians(1.1), Math.toRadians(36)), new IlvCoordinate(Math.toRadians(1.5), Math.toRadians(36.5)));
    IlvGraphicLayerDataSource ds = new IlvGraphicLayerDataSource();
    ds.add(lov);
    dataSourceModel.insert(ds);
    IlvMapLayer lovLayer = ds.getInsertionLayer();
    lovLayer.setAllowingMoveObjects(true);
    lovLayer.setName("Line of Sight");//$NON-NLS-1$
    lovLayer.setStyle(style);
    // insert it on the manager's map layer tree
    ltm.addChild(null, lovLayer);
    IlvAltitudeVisibilityChart chart = new DemoAltitudeChart(view.getManager(), lov);
    getContentPane().add(chart, BorderLayout.LINE_END);
    // JV-2857 - allow edition of line of visibility
    IlvMapSelectionFactory.setEditable(lov, true);
    try {
      ds.start();
    } catch (Exception e) {
      e.printStackTrace();
    }
  }

  /**
   * Main method
   * @param args ignored parameter.
   */
  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() {
        Override
        public void run() {
        final JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        TerrainDemo demo = new TerrainDemo();
        frame.getContentPane().add(demo);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setTitle("Terrain demo");//$NON-NLS-1$
        frame.pack();
        frame.setVisible(true);        
      }
    });
  }

  private static URL findURL(String resource) {
    URL rtnURL = null;
    boolean exists = false;
    try {
      exists = new File(resource).exists();
    } catch (SecurityException e) {
      // applet
    }
    if (exists) {
      try {
        rtnURL = new File(resource).toURI().toURL();
      } catch (Exception e) {
        e.printStackTrace();
      }
    } else {
      rtnURL = TerrainDemo.class.getResource(resource);
    }
    return rtnURL;
  }
}