import type Accessor from "../../core/Accessor.js";
import type AreaMeasurement2DViewModel from "../AreaMeasurement2D/AreaMeasurement2DViewModel.js";
import type AreaMeasurement3DViewModel from "../AreaMeasurement3D/AreaMeasurement3DViewModel.js";
import type DirectLineMeasurement3DViewModel from "../DirectLineMeasurement3D/DirectLineMeasurement3DViewModel.js";
import type DistanceMeasurement2DViewModel from "../DistanceMeasurement2D/DistanceMeasurement2DViewModel.js";
import type { SystemOrAreaUnit, SystemOrLengthUnit } from "../../core/units.js";
import type { MapViewOrSceneView } from "../../views/MapViewOrSceneView.js";
import type { MeasurementState } from "../types.js";
import type { MeasurementComponentType } from "./types.js";

export interface MeasurementViewModelProperties extends Partial<Pick<MeasurementViewModel, "activeTool" | "areaUnit" | "linearUnit" | "view">> {}

/**
 * Provides the logic for the [Measurement](https://developers.arcgis.com/javascript/latest/references/core/widgets/Measurement/) widget.
 *
 * @since 4.13
 * @see [Measurement](https://developers.arcgis.com/javascript/latest/references/core/widgets/Measurement/)
 * @see [Programming patterns: Widget viewModel pattern](https://developers.arcgis.com/javascript/latest/programming-patterns/#widget-viewmodel-pattern)
 */
export default class MeasurementViewModel extends Accessor {
  constructor(properties?: MeasurementViewModelProperties);
  /**
   * Specifies the current measurement tool to display. Setting its value to `area` activates
   * the area measurement tool and it works for both [MapView](https://developers.arcgis.com/javascript/latest/references/core/views/MapView/) and
   * [SceneView](https://developers.arcgis.com/javascript/latest/references/core/views/SceneView/). To measure distance in a [MapView](https://developers.arcgis.com/javascript/latest/references/core/views/MapView/)
   * set the property to `distance` and in a [SceneView](https://developers.arcgis.com/javascript/latest/references/core/views/SceneView/) set it to `direct-line`.
   * If this property is not set, the widget will not be displayed.
   *
   * @example
   * // To create the Measurement widget with SceneView's linear measurement widget active.
   * let measurement = new Measurement({
   *   viewModel: {
   *     view: view,
   *     activeTool: "direct-line"
   *   }
   * });
   */
  accessor activeTool: MeasurementComponentType | null | undefined;
  /**
   * View model of the active measurement widget.
   *
   * @example
   * // Print the active view model to the console.
   * let measurement = new Measurement({
   *   viewModel: {
   *     areaUnit: "square-us-feet",
   *     view: view,
   *     activeTool: "area"
   *   }
   * });
   * console.log("Active ViewModel: ", measurement.viewModel.activeViewModel);
   */
  get activeViewModel(): ActiveMeasurementViewModel | null | undefined;
  /**
   * Unit system (imperial, metric) or specific unit used for displaying the area values.
   * Possible values are: `metric`, `imperial`, `square-inches`, `square-feet`, `square-us-feet`, `square-yards`, `square-miles`, `square-nautical-miles`, `square-meters`, `square-kilometers`, `acres`, `ares`, `hectares`.
   *
   * @example
   * // To create the Measurement widget that displays area in square US feet
   * let measurement = new Measurement({
   *   viewModel: {
   *     areaUnit: "square-us-feet",
   *     view: view,
   *     activeTool: "area"
   *   }
   * });
   *
   * // To display the current measurement unit for area
   * console.log("Current unit: ", measurement.viewModel.areaUnit);
   */
  accessor areaUnit: SystemOrAreaUnit;
  /**
   * Unit system (imperial, metric) or specific unit used for displaying the distance values.
   * Possible values are: `metric`, `imperial`, `inches`, `feet`, `us-feet`, `yards`, `miles`, `nautical-miles`, `meters`, `kilometers`.
   *
   * @example
   * // To create the Measurement widget that displays distance in yards
   * let measurement = new Measurement({
   *   viewModel: {
   *     linearUnit: "yards",
   *     view: view,
   *     activeTool: "distance"
   *   }
   * });
   *
   * // To display the current measurement unit for distance
   * console.log('Current unit: ', measurement.viewModel.linearUnit);
   */
  accessor linearUnit: SystemOrLengthUnit;
  /**
   * The ViewModel's state.
   *
   * Value       | Description
   * ------------|-------------
   * disabled    | not ready yet
   * ready       | ready for measuring
   * measuring   | measuring has started
   * measured    | measuring has finished
   *
   * @default "disabled"
   * @example
   * // To display the state of the AreaMeasurement2D widget
   * let measurement = new Measurement({
   *   view: view,
   *   activeTool: "area"
   * });
   * reactiveUtils.watch(
   *   () => measurement.viewModel.state,
   *   (state) => console.log("Current state: ", state)
   * );
   */
  get state(): MeasurementState;
  /**
   * A reference to the [MapView](https://developers.arcgis.com/javascript/latest/references/core/views/MapView/) or [SceneView](https://developers.arcgis.com/javascript/latest/references/core/views/SceneView/).
   *
   * @example
   * // Add the measurement widget to the upper right hand corner.
   * const measurement = new Measurement({
   *   viewModel: {
   *     view: view,
   *     activeTool = "distance";
   *   }
   * });
   * view.ui.add(measurement, "top-right");
   */
  accessor view: MapViewOrSceneView | null | undefined;
}

export type ActiveMeasurementViewModel = AreaMeasurement2DViewModel | AreaMeasurement3DViewModel | DirectLineMeasurement3DViewModel | DistanceMeasurement2DViewModel;