package com.esri.samples.analysis.viewshed_location;

import javafx.fxml.FXML;
import javafx.scene.control.ColorPicker;
import javafx.scene.control.Slider;

import org.controlsfx.control.RangeSlider;
import org.controlsfx.control.ToggleSwitch;

import com.esri.arcgisruntime.analysis.LocationViewshed;
import com.esri.arcgisruntime.analysis.Viewshed;
import com.esri.arcgisruntime.geometry.Point;
import com.esri.arcgisruntime.layers.ArcGISSceneLayer;
import com.esri.arcgisruntime.mapping.ArcGISScene;
import com.esri.arcgisruntime.mapping.ArcGISTiledElevationSource;
import com.esri.arcgisruntime.mapping.Basemap;
import com.esri.arcgisruntime.mapping.Surface;
import com.esri.arcgisruntime.mapping.view.AnalysisOverlay;
import com.esri.arcgisruntime.mapping.view.Camera;
import com.esri.arcgisruntime.mapping.view.LayerSceneProperties;
import com.esri.arcgisruntime.mapping.view.SceneView;

public class ViewshedLocationController {

  @FXML private SceneView sceneView;
  @FXML private ToggleSwitch moveWithMouseToggle;
  @FXML private ToggleSwitch visibilityToggle;
  @FXML private ToggleSwitch frustumToggle;
  @FXML private Slider headingSlider;
  @FXML private Slider pitchSlider;
  @FXML private Slider horizontalAngleSlider;
  @FXML private Slider verticalAngleSlider;
  @FXML private RangeSlider distanceSlider;
  @FXML private ColorPicker visibleColorPicker;
  @FXML private ColorPicker obstructedColorPicker;
  @FXML private ColorPicker frustumColorPicker;

  public void initialize() {
    // create a scene and add a basemap to it
    ArcGISScene scene = new ArcGISScene();
    scene.setBasemap(Basemap.createImagery());
    sceneView.setArcGISScene(scene);

    // set the camera
    Camera camera = new Camera(48.4, -4.50, 100.0, 10.0, 70, 0.0);
    sceneView.setViewpointCamera(camera);

    // add base surface for elevation data
    Surface surface = new Surface();
    final String localElevationImageService = "http://scene.arcgis" +
        ".com/arcgis/rest/services/BREST_DTM_1M/ImageServer";
    surface.getElevationSources().add(new ArcGISTiledElevationSource(localElevationImageService));
    scene.setBaseSurface(surface);

    // add a scene layer
    final String buildings = "http://tiles.arcgis.com/tiles/P3ePLMYs2RVChkJx/arcgis/rest/services/Buildings_Brest/SceneServer/layers/0";
    ArcGISSceneLayer sceneLayer = new ArcGISSceneLayer(buildings);
    scene.getOperationalLayers().add(sceneLayer);

    // create a viewshed from the camera
    Point location = new Point(-4.50, 48.4,100.0);
    LocationViewshed viewshed = new LocationViewshed(location, 10.0, 70.0, 90.0, 30.0, 1.0, 500.0,
        LayerSceneProperties.SurfacePlacement.RELATIVE);

    // create an analysis overlay to add the viewshed to the scene view
    AnalysisOverlay analysisOverlay = new AnalysisOverlay();
    analysisOverlay.getAnalyses().add(viewshed);
    sceneView.getAnalysisOverlays().add(analysisOverlay);

    // toggle visibility
    visibilityToggle.selectedProperty().addListener(e -> viewshed.setVisible(visibilityToggle.isSelected()));
    // TODO: toggle frustum
    // heading slider
    headingSlider.valueProperty().addListener(e -> viewshed.setHeading(headingSlider.getValue()));
    // pitch slider
    pitchSlider.valueProperty().addListener(e -> viewshed.setPitch(pitchSlider.getValue()));
    // horizontal angle slider
    horizontalAngleSlider.valueProperty().addListener(e -> viewshed.setHorizontalAngle(horizontalAngleSlider.getValue()));
    // vertical angle slider
    verticalAngleSlider.valueProperty().addListener(e -> viewshed.setVerticalAngle(verticalAngleSlider
        .getValue()));
    // distance slider
    distanceSlider.lowValueProperty().addListener(e -> viewshed.setMinDistance(distanceSlider.getLowValue()));
    distanceSlider.highValueProperty().addListener(e -> viewshed.setMaxDistance(distanceSlider.getHighValue()));
    // TODO: color pickers
  }

  /**
   * Stops the animation and disposes of application resources.
   */
  void terminate() {

    if (sceneView != null) {
      sceneView.dispose();
    }
  }

}

@@ -148,16 +148,82 @@
 .Slider;
+%0Aimport javafx.scene.paint.Color;%0Aimport javafx.scene.paint.Paint;
 %0A%0Aimport
@@ -1737,140 +1737,8 @@
 );%0A%0A
-    // set the camera%0A    Camera camera = new Camera(48.4, -4.50, 100.0, 10.0, 70, 0.0);%0A    sceneView.setViewpointCamera(camera);%0A%0A
     
@@ -2605,24 +2605,155 @@
 RELATIVE);%0A%0A
+    // set the camera%0A    Camera camera = new Camera(location, 200.0, 20.0, 70.0, 0.0);%0A    sceneView.setViewpointCamera(camera);%0A%0A
     // creat
@@ -3945,27 +3945,858 @@
  // 
-TODO: color pickers
+colors%0A    visibleColorPicker.valueProperty().addListener(e -%3E Viewshed.setVisibleColor(colorToInt(visibleColorPicker%0A        .getValue())));%0A    obstructedColorPicker.valueProperty().addListener(e -%3E Viewshed.setObstructedColor(colorToInt(obstructedColorPicker%0A        .getValue())));%0A    frustumColorPicker.valueProperty().addListener(e -%3E Viewshed.setFrustumOutlineColor(colorToInt(frustumColorPicker%0A        .getValue())));%0A  %7D%0A%0A  /**%0A   * Parses a Color into an ARGB %22packed%22 integer.%0A   *%0A   * @param c color%0A   * @return packed integer representation of the color%0A   */%0A  private int colorToInt(Color c) %7B%0A    String hex = String.format(%220x%2502X%2502X%2502X%2502X%22,%0A        (int)(c.getOpacity() * 255),%0A        (int)(c.getRed() * 255),%0A        (int)(c.getGreen() * 255),%0A        (int)(c.getBlue() * 255)%0A    );%0A    return Long.decode(hex).intValue();
 %0A  %7D

Add color options