import type Color from "../../../Color.js";
import type MapView from "../../../views/MapView.js";
import type SnappingOptions from "../../../views/interactive/snapping/SnappingOptions.js";
import type { EventedAccessor } from "../../../core/Evented.js";
import type { LengthUnit } from "../../../core/units.js";
import type { GridPlacementState } from "./types.js";
import type { SnappingOptionsProperties } from "../../../views/interactive/snapping/SnappingOptions.js";

export interface GridControlsViewModelProperties extends Partial<Pick<GridControlsViewModel, "dynamicScaling" | "gridColor" | "interactivePlacementState" | "majorLineInterval" | "placementDisabled" | "rotateWithMap" | "rotation" | "snappingEnabled" | "spacing" | "view">> {
  /** This is the snapping options object that will be configured by the 'enable snapping' property. */
  snappingOptions?: SnappingOptionsProperties | null;
  /**
   * Unit of measure (foot, meter, etc) used when defining the [spacing](https://developers.arcgis.com/javascript/latest/references/core/widgets/support/GridControls/GridControlsViewModel/#spacing) grid cell.
   * Note that units are defined relatively to the map's spatial reference length unit,
   * which will not correspond to geographic distance unless using a special-purpose basemap
   * within a supported target area.
   *
   * When using Web Mercator, the projection defines the length of a meter in projection system units;
   * this length is equal to a geographic meter only at the equator. On screen, the size of the grid cells is constant
   * from the equator to the poles, but the real-world size of the grid cell is much larger further from the equator.
   *
   * The length of the grid cells can usefully correspond to a geographic length when the Grid is used with an
   * appropriate spatial reference (for example a local system or a State Plane system) within the reference's area of interst.
   */
  unit?: LengthUnit;
}

export interface GridControlsViewModelEvents {}

/**
 * Provides the logic for the [GridControls](https://developers.arcgis.com/javascript/latest/references/core/widgets/support/GridControls/).
 *
 * [GridControls](https://developers.arcgis.com/javascript/latest/references/core/widgets/support/GridControls/) is integrated into the [Editor](https://developers.arcgis.com/javascript/latest/references/core/widgets/Editor/) and [Sketch](https://developers.arcgis.com/javascript/latest/references/core/widgets/Sketch/) widgets
 * via the [SnappingControls](https://developers.arcgis.com/javascript/latest/references/core/widgets/support/SnappingControls/) widget. Display of the GridControls widget in those contexts
 * can be controlled through each widget's respective [GridControls.visibleElements](https://developers.arcgis.com/javascript/latest/references/core/widgets/support/GridControls/#visibleElements) property.
 *
 * @since 4.31
 * @see [GridControls](https://developers.arcgis.com/javascript/latest/references/core/widgets/support/GridControls/) - _Deprecated since 4.33. Use the [Grid Controls component](https://developers.arcgis.com/javascript/latest/references/map-components/components/arcgis-grid-controls/) instead._
 * @see [SnappingOptions](https://developers.arcgis.com/javascript/latest/references/core/views/interactive/snapping/SnappingOptions/)
 * @see [SnappingControls](https://developers.arcgis.com/javascript/latest/references/core/widgets/support/SnappingControls/)
 * @see [Programming patterns: Widget viewModel pattern](https://developers.arcgis.com/javascript/latest/programming-patterns/#widget-viewmodel-pattern)
 */
export default class GridControlsViewModel extends EventedAccessor {
  constructor(properties?: GridControlsViewModelProperties);
  /**
   * Returns `true` if the grid is enabled for display.
   * Use [trySetDisplayEnabled()](https://developers.arcgis.com/javascript/latest/references/core/widgets/support/GridControls/GridControlsViewModel/#trySetDisplayEnabled) to enable or disable grid display.
   */
  get displayEnabled(): boolean;
  /**
   * Returns `true` if the grid is set to scale dynamically. When dynamic scaling is enabled,
   * grid cells are added or removed to ensure that grid cells are a reasonable size on screen as the user zooms.
   * The way additional grid lines are shown is controlled by the [majorLineInterval](https://developers.arcgis.com/javascript/latest/references/core/widgets/support/GridControls/GridControlsViewModel/#majorLineInterval) property.
   */
  accessor dynamicScaling: boolean;
  /**
   * Returns the effective spacing of grid lines after applying the [dynamicScaling](https://developers.arcgis.com/javascript/latest/references/core/widgets/support/GridControls/GridControlsViewModel/#dynamicScaling)
   * setting at the current view scale.
   */
  get effectiveSpacingAfterDynamicScaling(): number | null;
  /**
   * Sets the color used for grid display. When major/minor lines are shown [majorLineInterval](https://developers.arcgis.com/javascript/latest/references/core/widgets/support/GridControls/GridControlsViewModel/#majorLineInterval) is between 2 and 15.
   * The minor line will be shown at the provided color with 50% opacity.
   */
  accessor gridColor: Color | null | undefined;
  /** Returns `true` if the grid is in a valid state for manually setting grid properties or starting an interactive placement. */
  get gridControlsEnabled(): boolean;
  /**
   * True if the grid is currently not displayed (and therefore also not a valid snap target),
   * because [dynamicScaling](https://developers.arcgis.com/javascript/latest/references/core/widgets/support/GridControls/GridControlsViewModel/#dynamicScaling) is off and the grid cells are too small
   * to render at the current scale.
   */
  get gridOutOfScale(): boolean;
  /**
   * Sets the interactive placement state, either starting or ending a draw operation that implicitly adjusts the grid.
   * Interactive placement allows the user to define the center of the grid, then the scale and rotation of the grid by
   * drawing a second point. Setting this to "place" allows the user to move the grid center only. Setting this to "rotate"
   * keeps the scale and center of the grid constant while rotating the grid by defining a second point.
   */
  accessor interactivePlacementState: GridPlacementState | null | undefined;
  /**
   * Controls the number of grid lines shown at 50% opacity between opaque grid lines when using [dynamicScaling](https://developers.arcgis.com/javascript/latest/references/core/widgets/support/GridControls/GridControlsViewModel/#dynamicScaling).
   *
   * @default 10
   */
  accessor majorLineInterval: number;
  /**
   * True if the spacing input should be shown for the current view.
   *
   * Common spatial references, like Web Mercator and WGS84, will show
   * a significant mismatch between the spacing defined for the grid and
   * the actual length of grid cells. This mismatch varies with position
   * on the map and with direction (the mismatch is different depending on line angle).
   *
   * Because the spacing input is inappropriate and misleading in common
   * web mapping use cases, it should be hidden from the user to avoid
   * conveying a false sense of precision.
   *
   * For specialized planar spatial references, it is more likely that the user
   * is an experience GIS professional with an understanding of projections
   * and the consequent distortions. To enable these users to complete their
   * work, users of maps with these spatial references can be given direct
   * access to specify grid length.
   */
  get numericSpacingInputShouldBeVisible(): boolean;
  /**
   * If true, interactive placement tools should be disabled.
   *
   * @default false
   * @since 4.33
   */
  accessor placementDisabled: boolean;
  /**
   * Determines the behavior of the grid when the map's viewpoint is rotated. When true, rotating the map
   * also rotates the grid on screen. When false, rotating the viewpoint does not rotate the grid.
   *
   * Note that [rotation](https://developers.arcgis.com/javascript/latest/references/core/widgets/support/GridControls/GridControlsViewModel/#rotation) is applied independently and can be configured regardless of how this setting is configured.
   *
   * @default true
   */
  accessor rotateWithMap: boolean;
  /** The grid's rotation in radians. */
  accessor rotation: number;
  /**
   * Controls snapping behavior if [snappingOptions](https://developers.arcgis.com/javascript/latest/references/core/widgets/support/GridControls/GridControlsViewModel/#snappingOptions) has been defined.
   * If [snappingOptions](https://developers.arcgis.com/javascript/latest/references/core/widgets/support/GridControls/GridControlsViewModel/#snappingOptions) have been defined, disabling or enabling grid snapping will
   * also disable or enable grid display.
   *
   * @default false
   */
  accessor snappingEnabled: boolean;
  /** This is the snapping options object that will be configured by the 'enable snapping' property. */
  get snappingOptions(): SnappingOptions | null | undefined;
  set snappingOptions(value: SnappingOptionsProperties | null | undefined);
  /**
   * Length of a grid cell. Grid cells are always square. Defined in [unit](https://developers.arcgis.com/javascript/latest/references/core/widgets/support/GridControls/GridControlsViewModel/#unit).
   *
   * @default 1
   */
  accessor spacing: number;
  /**
   * Unit of measure (foot, meter, etc) used when defining the [spacing](https://developers.arcgis.com/javascript/latest/references/core/widgets/support/GridControls/GridControlsViewModel/#spacing) grid cell.
   * Note that units are defined relatively to the map's spatial reference length unit,
   * which will not correspond to geographic distance unless using a special-purpose basemap
   * within a supported target area.
   *
   * When using Web Mercator, the projection defines the length of a meter in projection system units;
   * this length is equal to a geographic meter only at the equator. On screen, the size of the grid cells is constant
   * from the equator to the poles, but the real-world size of the grid cell is much larger further from the equator.
   *
   * The length of the grid cells can usefully correspond to a geographic length when the Grid is used with an
   * appropriate spatial reference (for example a local system or a State Plane system) within the reference's area of interst.
   */
  get unit(): LengthUnit | undefined;
  set unit(value: LengthUnit);
  /** The view from which the widget will operate. */
  accessor view: MapView | null | undefined;
  /**
   * Try to enable or disable grid display. Will fail if the view is not yet ready to display a grid.
   *
   * @param visible - Controls whether to try to enable or disable grid display.
   */
  trySetDisplayEnabled(visible: boolean): void;
}