import type Accessor from "../../core/Accessor.js";
import type MapView from "../../views/MapView.js";
import type SnappingOptions from "../../views/interactive/snapping/SnappingOptions.js";
import type { SystemOrAreaUnit } from "../../core/units.js";
import type { AreaMeasurement, AreaMeasurementLabel, MeasurementState } from "../types.js";
import type { SnappingOptionsProperties } from "../../views/interactive/snapping/SnappingOptions.js";

export interface AreaMeasurement2DViewModelProperties extends Partial<Pick<AreaMeasurement2DViewModel, "view">> {
  /**
   * The [SnappingOptions](https://developers.arcgis.com/javascript/latest/references/core/views/interactive/snapping/SnappingOptions/) for sketching.
   * It supports [self](https://developers.arcgis.com/javascript/latest/references/core/views/interactive/snapping/SnappingOptions/#selfEnabled) and
   * [feature](https://developers.arcgis.com/javascript/latest/references/core/views/interactive/snapping/SnappingOptions/#featureEnabled) snapping.
   *
   * @beta
   * @since 4.32
   */
  snappingOptions?: SnappingOptionsProperties;
  /**
   * Unit system (imperial, metric) or specific unit used for displaying the area values.
   * Possible values are listed in [unitOptions](https://developers.arcgis.com/javascript/latest/references/core/widgets/AreaMeasurement2D/AreaMeasurement2DViewModel/#unitOptions).
   *
   * @example
   * // To create the AreaMeasurement2D widget that displays area in square US feet
   * let measurementWidget = new AreaMeasurement2D({
   *   viewModel: {
   *     view: view,
   *     unit: "square-us-feet"
   *   }
   * });
   *
   * // To display the current measurement unit
   * console.log('Current unit: ', measurementWidget.viewModel.unit);
   */
  unit?: SystemOrAreaUnit | null;
  /**
   * List of available units and unit systems (imperial, metric) for displaying the area values.
   * By default, the following units are included: `metric`, `imperial`, `square-inches`, `square-feet`, `square-us-feet`, `square-yards`, `square-miles`, `square-meters`, `square-kilometers`, `acres`, `ares`, `hectares`.
   * Possible [unit](https://developers.arcgis.com/javascript/latest/references/core/widgets/AreaMeasurement2D/AreaMeasurement2DViewModel/#unit) values can only be a subset of this list.
   *
   * @example
   * // To display the available units to the console
   * let measurementWidget = new AreaMeasurement2D({
   *   view: view
   * });
   * console.log('All units: ', measurementWidget.viewModel.unitOptions.join(", "));
   */
  unitOptions?: SystemOrAreaUnit[] | null;
}

/**
 * Provides the logic for the [AreaMeasurement2D](https://developers.arcgis.com/javascript/latest/references/core/widgets/AreaMeasurement2D/) widget and [component](https://developers.arcgis.com/javascript/latest/references/map-components/components/arcgis-area-measurement-2d/).
 *
 * @since 4.10
 * @see [AreaMeasurement2D](https://developers.arcgis.com/javascript/latest/references/core/widgets/AreaMeasurement2D/) widget
 * @see [Area Measurement 2D component](https://developers.arcgis.com/javascript/latest/references/map-components/components/arcgis-area-measurement-2d/)
 * @see [Programming patterns: Widget viewModel pattern](https://developers.arcgis.com/javascript/latest/programming-patterns/#widget-viewmodel-pattern)
 */
export default class AreaMeasurement2DViewModel extends Accessor {
  constructor(properties?: AreaMeasurement2DViewModelProperties);
  /**
   * The area and perimeter of the measurement polygon in square meters and meters respectively.
   *
   * @example
   * // After creating and adding the AreaMeasurement2D widget
   * let measurementWidget = new AreaMeasurement2D({
   *   view: view
   * });
   * view.ui.add(measurementWidget, "top-right");
   *
   * // Raw measurements (in meters) can be accessed from this property
   * reactiveUtils.watch(
   * () => measurementWidget.viewModel.measurement,
   *   (measurement) => {
   *     console.log(
   *        "Area: ", measurement.area,
   *        "Perimeter: ", measurement.perimeter
   *     );
   *   }
   * );
   */
  get measurement(): AreaMeasurement | null | undefined;
  /**
   * This property returns the locale specific representation of the area and perimeter.
   * Areas and perimeters are rounded to two decimal places. Areas are sourced from the [measurement](https://developers.arcgis.com/javascript/latest/references/core/widgets/AreaMeasurement2D/AreaMeasurement2DViewModel/#measurement) property
   * (in square meters) and converted to the user defined units/system.
   *
   * @example
   * // After creating and adding the AreaMeasurement2D widget
   * let measurementWidget = new AreaMeasurement2D({
   *   view: view
   * });
   * view.ui.add(measurementWidget, "top-right");
   *
   * // Measurement labels can be accessed from this property
   * reactiveUtils.watch(
   * () => measurementWidget.viewModel.measurementLabel,
   *   (label) => {
   *     console.log(
   *        "Area: ", label.area,
   *        "Perimeter: ", label.perimeter
   *     );
   *   }
   * );
   */
  get measurementLabel(): AreaMeasurementLabel | null | undefined;
  /**
   * The [SnappingOptions](https://developers.arcgis.com/javascript/latest/references/core/views/interactive/snapping/SnappingOptions/) for sketching.
   * It supports [self](https://developers.arcgis.com/javascript/latest/references/core/views/interactive/snapping/SnappingOptions/#selfEnabled) and
   * [feature](https://developers.arcgis.com/javascript/latest/references/core/views/interactive/snapping/SnappingOptions/#featureEnabled) snapping.
   *
   * @beta
   * @since 4.32
   */
  get snappingOptions(): SnappingOptions;
  set snappingOptions(value: SnappingOptionsProperties);
  /**
   * 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 measurementWidget = new AreaMeasurement2D({
   *   view: view
   * });
   * reactiveUtils.watch(
   *   () => measurementWidget.viewModel.state,
   *   (state) => console.log("Current state: ", state)
   * );
   */
  get state(): MeasurementState;
  /**
   * Unit system (imperial, metric) or specific unit used for displaying the area values.
   * Possible values are listed in [unitOptions](https://developers.arcgis.com/javascript/latest/references/core/widgets/AreaMeasurement2D/AreaMeasurement2DViewModel/#unitOptions).
   *
   * @example
   * // To create the AreaMeasurement2D widget that displays area in square US feet
   * let measurementWidget = new AreaMeasurement2D({
   *   viewModel: {
   *     view: view,
   *     unit: "square-us-feet"
   *   }
   * });
   *
   * // To display the current measurement unit
   * console.log('Current unit: ', measurementWidget.viewModel.unit);
   */
  get unit(): SystemOrAreaUnit;
  set unit(value: SystemOrAreaUnit | null | undefined);
  /**
   * List of available units and unit systems (imperial, metric) for displaying the area values.
   * By default, the following units are included: `metric`, `imperial`, `square-inches`, `square-feet`, `square-us-feet`, `square-yards`, `square-miles`, `square-meters`, `square-kilometers`, `acres`, `ares`, `hectares`.
   * Possible [unit](https://developers.arcgis.com/javascript/latest/references/core/widgets/AreaMeasurement2D/AreaMeasurement2DViewModel/#unit) values can only be a subset of this list.
   *
   * @example
   * // To display the available units to the console
   * let measurementWidget = new AreaMeasurement2D({
   *   view: view
   * });
   * console.log('All units: ', measurementWidget.viewModel.unitOptions.join(", "));
   */
  get unitOptions(): SystemOrAreaUnit[];
  set unitOptions(value: SystemOrAreaUnit[] | null | undefined);
  /**
   * The view from which the widget will operate.
   *
   * @example
   * // To create the AreaMeasurement2D widget with the view property
   * let measurementWidget = new AreaMeasurement2D({
   *   viewModel: {
   *     view: view
   *   }
   * });
   */
  accessor view: MapView | null | undefined;
  /**
   * Clears the current measurement.
   *
   * @since 4.16
   */
  clear(): void;
  /**
   * Starts a new measurement.
   *
   * @since 4.16
   * @example
   * const areaMeasurement2DViewModel = new AreaMeasurement2DViewModel({
   *   view: view,
   *   unit: "square-yards"
   * });
   *
   * await areaMeasurement2DViewModel.start();
   */
  start(): Promise<void>;
}