import type Accessor from "../../../core/Accessor.js";
import type Collection from "../../../core/Collection.js";
import type FeatureSnappingLayerSource from "./FeatureSnappingLayerSource.js";
import type { FeatureSnappingLayerSourceProperties } from "./FeatureSnappingLayerSource.js";
import type { ReadonlyArrayOrCollection } from "../../../core/Collection.js";

export interface SnappingOptionsProperties extends Partial<Pick<SnappingOptions, "attributeRulesEnabled" | "distance" | "enabled" | "featureEnabled" | "gridEnabled" | "selfEnabled">> {
  /** List of sources for feature snapping. Please refer to [FeatureSnappingLayerSource](https://developers.arcgis.com/javascript/latest/api-reference/esri-views-interactive-snapping-FeatureSnappingLayerSource.html) for additional information on what layer sources are supported. */
  featureSources?: ReadonlyArrayOrCollection<FeatureSnappingLayerSourceProperties>;
}

/**
 * The `SnappingOptions` allows users to configure snapping for their editing or drawing experience in both the [Sketch#snappingOptions](https://developers.arcgis.com/javascript/latest/api-reference/esri-widgets-Sketch.html#snappingOptions) and [Editor#snappingOptions](https://developers.arcgis.com/javascript/latest/api-reference/esri-widgets-Editor.html#snappingOptions) widgets.
 *
 * Snapping options provide the ability to specify whether an application will utilize self snapping, feature snapping, or both. Both are described below.
 *
 * It is also possible to toggle snapping by pressing and holding down the `CTRL` key. This toggles the snapping on/off.
 *
 * #### Self snapping (Geometry guides)
 * Self snapping is set via the [selfEnabled](https://developers.arcgis.com/javascript/latest/api-reference/esri-views-interactive-snapping-SnappingOptions.html#selfEnabled) property. This means that while a user is actively creating or updating a feature or graphic, they will see visualizations to help identify perpendicular and parallel lines, in addition to visualizations which aid in snapping to an extension of an existing feature. The following briefly demonstrates what self snapping looks like in a 2D application. Although this is shown for 2D, the same premise applies for 3D as well.
 *
 * ![self-snapping](https://developers.arcgis.com/javascript/latest/assets/img/apiref/widgets/sketch/snapping-self-2d.gif)
 * #### Feature snapping
 * Feature snapping is set via the [featureEnabled](https://developers.arcgis.com/javascript/latest/api-reference/esri-views-interactive-snapping-SnappingOptions.html#featureEnabled) property. It provides the ability to snap vertices of a graphic or feature that is currently being drawn or reshaped to that of an existing feature's vertex, edge, or end point. These existing features belong to layers within the [Map](https://developers.arcgis.com/javascript/latest/api-reference/esri-Map.html) and must be specified in the [featureSources](https://developers.arcgis.com/javascript/latest/api-reference/esri-views-interactive-snapping-SnappingOptions.html#featureSources) property. The following two images demonstrate feature snapping in a 2D application. Similar to self snapping, the same premise applies for 3D as well.
 *
 * ![feature-snapping-create](https://developers.arcgis.com/javascript/latest/assets/img/apiref/widgets/sketch/snapping-feature-2d.gif)
 *
 * The above shows feature snapping to an existing feature's vertex endpoint and edge while creating a new feature. The bottom demonstrates taking an existing feature and reshaping its geometry to snap to another feature's vertex points.
 *
 * ![feature-snapping-update](https://developers.arcgis.com/javascript/latest/assets/img/apiref/widgets/sketch/snapping-reshape-2d.gif)
 *
 * > [!WARNING]
 * >
 * > **Things to consider:**
 * > Layer types currently supported for snapping are: [FeatureLayer](https://developers.arcgis.com/javascript/latest/api-reference/esri-layers-FeatureLayer.html), [GraphicsLayer](https://developers.arcgis.com/javascript/latest/api-reference/esri-layers-GraphicsLayer.html) (except Mesh geometries),
 * > [GeoJSONLayer](https://developers.arcgis.com/javascript/latest/api-reference/esri-layers-GeoJSONLayer.html), [WFSLayer](https://developers.arcgis.com/javascript/latest/api-reference/esri-layers-WFSLayer.html), [CSVLayer](https://developers.arcgis.com/javascript/latest/api-reference/esri-layers-CSVLayer.html),
 * > [MapNotesLayer](https://developers.arcgis.com/javascript/latest/api-reference/esri-layers-MapNotesLayer.html) (2D only), [3D Object SceneLayer](https://developers.arcgis.com/javascript/latest/api-reference/esri-layers-SceneLayer.html) (3D only), and
 * > [BuildingSceneLayer](https://developers.arcgis.com/javascript/latest/api-reference/esri-layers-BuildingSceneLayer.html) (3D only).
 * > Snapping is not yet implemented when using the [Sketch widget's](https://developers.arcgis.com/javascript/latest/api-reference/esri-widgets-Sketch.html) circle tool. It will be addressed in a future release.
 * > Enabling snapping via the `CTRL` key is not currently supported using the [Sketch widget's](https://developers.arcgis.com/javascript/latest/api-reference/esri-widgets-Sketch.html) rectangle and circle tools. However, snapping can still be activated by setting the [enabled](https://developers.arcgis.com/javascript/latest/api-reference/esri-views-interactive-snapping-SnappingOptions.html#enabled) property to `true` in the [Sketch widget](https://developers.arcgis.com/javascript/latest/api-reference/esri-widgets-Sketch.html) or its [view model](https://developers.arcgis.com/javascript/latest/api-reference/esri-widgets-Sketch-SketchViewModel.html). *Note that this enables snapping for all tools. This behavior is subject to change in a future release.*
 *
 * Name | Details | 3D Example | 2D Example  |
 * ---------|---------|----------|:-----------:|
 * Rectangle | Snap lines that are perpendicular to each other | <img alt="Rectangle" src="https://developers.arcgis.com/javascript/latest/assets/img/apiref/widgets/sketch/snapping-rectangle.png" width="268px"> | <img alt="Rectangle-2d" src="https://developers.arcgis.com/javascript/latest/assets/img/apiref/widgets/sketch/snapping-rectangle-2d.png" width="268px"> |
 * Parallel | Snap to all parallel lines | <img alt="Parallel" src="https://developers.arcgis.com/javascript/latest/assets/img/apiref/widgets/sketch/snapping-parallel.png" width="268px"> | <img alt="Parallel-2d" src="https://developers.arcgis.com/javascript/latest/assets/img/apiref/widgets/sketch/snapping-parallel-2.png" width="268px"> |
 * Extension | Snap to an extension of the current shape | <img alt="Extension" src="https://developers.arcgis.com/javascript/latest/assets/img/apiref/widgets/sketch/snapping-extension.png" width="268px"> | <img alt="Extension-2" src="https://developers.arcgis.com/javascript/latest/assets/img/apiref/widgets/sketch/snapping-extension-2.png" width="268px"> |
 * Vertex (as seen when updating geometries)| Snap vertices to an existing vertex | <img alt="Vertex" src="https://developers.arcgis.com/javascript/latest/assets/img/apiref/widgets/sketch/snapping-vertex-3d.png" width="143px"> | <img alt="Vertex-2" src="https://developers.arcgis.com/javascript/latest/assets/img/apiref/widgets/sketch/snapping-vertex-2.png" width="143px"> |
 *
 * @since 4.19
 * @see [FeatureSnappingLayerSource](https://developers.arcgis.com/javascript/latest/api-reference/esri-views-interactive-snapping-FeatureSnappingLayerSource.html)
 * @see [Sketch](https://developers.arcgis.com/javascript/latest/api-reference/esri-widgets-Sketch.html)
 * @see [SketchViewModel](https://developers.arcgis.com/javascript/latest/api-reference/esri-widgets-Sketch-SketchViewModel.html)
 * @see [Editor](https://developers.arcgis.com/javascript/latest/api-reference/esri-widgets-Editor.html)
 * @see [Sample - Sketch widget](https://developers.arcgis.com/javascript/latest/sample-code/sketch-geometries/)
 * @see [Sample - Sketch in 3D](https://developers.arcgis.com/javascript/latest/sample-code/sketch-3d/)
 * @see [Sample - Edit features in 3D with the Editor widget](https://developers.arcgis.com/javascript/latest/sample-code/editor-3d/)
 * @see [Sample - Editor widget with configurations](https://developers.arcgis.com/javascript/latest/sample-code/widgets-editor-configurable/)
 * @see [Sample - Snapping with Sketch widget and Magnifier](https://developers.arcgis.com/javascript/latest/sample-code/sketch-snapping-magnifier/)
 * @example
 * // Create a new instance of Sketch, and set
 * // a layer for one of the featureSources property.
 * // This enables feature snapping on that layer.
 * const sketch = new Sketch({
 *   layer: graphicsLayer,
 *   view: view,
 *   snappingOptions: { // autocasts to SnappingOptions()
 *     enabled: true, // global snapping is turned on
 *     // assigns a collection of FeatureSnappingLayerSource() and enables feature snapping on this layer
 *     featureSources: [{ layer: graphicsLayer, enabled: true }]
 *   }
 * });
 */
export default class SnappingOptions extends Accessor {
  constructor(properties?: SnappingOptionsProperties);
  /**
   * When true, enables support for attribute rule-based snapping.
   * When enabled, resources needed for rule-based snapping, including any Utility Networks present
   * in the map, will be automatically loaded.
   *
   * @default false
   * @since 4.30
   */
  accessor attributeRulesEnabled: boolean;
  /**
   * Snapping distance for snapping in pixels.
   *
   * @default 5
   */
  accessor distance: number;
  /**
   * Global configuration to turn snapping on or off. Note that snapping is
   * turned off by default.
   *
   * @default false
   */
  accessor enabled: boolean;
  /**
   * Global configuration option to turn feature snapping on or off.
   *
   * @default true
   */
  accessor featureEnabled: boolean;
  /** List of sources for feature snapping. Please refer to [FeatureSnappingLayerSource](https://developers.arcgis.com/javascript/latest/api-reference/esri-views-interactive-snapping-FeatureSnappingLayerSource.html) for additional information on what layer sources are supported. */
  get featureSources(): Collection<FeatureSnappingLayerSource>;
  set featureSources(value: ReadonlyArrayOrCollection<FeatureSnappingLayerSourceProperties>);
  /**
   * Turns the grid on or off. The grid is a network of columns and rows used to divide the view into equal-area squares.
   * The [GridControls](https://developers.arcgis.com/javascript/latest/api-reference/esri-widgets-support-GridControls.html) provides a user interface to interact and configure the grid's properties.
   *
   * > [!WARNING]
   * >
   * > **Note**
   * >
   * > It is recommended to wait for the view to be loaded first before setting the `gridEnabled` prop in the [GridControls](https://developers.arcgis.com/javascript/latest/api-reference/esri-widgets-support-GridControls.html) constructor. The grid is dependent on the view to be loaded first for it to be displayed.
   * > - This grid is only supported in a 2D [MapView](https://developers.arcgis.com/javascript/latest/api-reference/esri-views-MapView.html).
   *
   * @default false
   * @since 4.31
   * @see [GridControls](https://developers.arcgis.com/javascript/latest/api-reference/esri-widgets-support-GridControls.html)
   * @example
   * // Turn on the grid programmatically for the GridControls.
   * // Wait for the view to load first.
   * view.when(() => {
   *   const gridControls = new GridControls({
   *     view,
   *     snappingOptions: {
   *       enabled: true,
   *       gridEnabled: true
   *     }
   *   });
   *   // Add GridControls to the view
   *   view.ui.add(gridControls, "top-left");
   * });
   */
  accessor gridEnabled: boolean;
  /**
   * Global configuration option to turn self snapping (within one feature while
   * either drawing or reshaping) on or off.
   *
   * @default true
   */
  accessor selfEnabled: boolean;
}