/// <reference path="../../index.d.ts" />
import type { PublicLitElement as LitElement } from "@arcgis/lumina";
import type { ArcgisReferenceElement, IconName } from "../types.js";
import type { MapViewOrSceneView } from "@arcgis/core/views/MapViewOrSceneView.js";
import type { MeasurementComponentType } from "@arcgis/core/widgets/Measurement/types.js";
import type { MeasurementWidget } from "@arcgis/core/widgets/Measurement.js";
import type { SystemOrAreaUnit, SystemOrLengthUnit } from "@arcgis/core/core/units.js";
import type { Icon } from "@esri/calcite-components/components/calcite-icon";
import type { MeasurementState } from "@arcgis/core/widgets/types.js";

/**
 * The Measurement component groups and manages multiple measurement tools and allows you to easily switch between them using
 * the [activeTool](https://developers.arcgis.com/javascript/latest/references/map-components/components/arcgis-measurement/#activeTool) property. The tools correspond to the measurement components for area and distance in 2D
 * [arcgis-area-measurement-2d](https://developers.arcgis.com/javascript/latest/references/map-components/components/arcgis-area-measurement-2d/), [arcgis-distance-measurement-2d](https://developers.arcgis.com/javascript/latest/references/map-components/components/arcgis-distance-measurement-2d/) and in 3D
 * [arcgis-area-measurement-3d](https://developers.arcgis.com/javascript/latest/references/map-components/components/arcgis-area-measurement-3d/), [arcgis-direct-line-measurement-3d](https://developers.arcgis.com/javascript/latest/references/map-components/components/arcgis-direct-line-measurement-3d/).
 *
 * This component follows a composite pattern that allows developers to configure the UI to best match their specific requirements.
 * The measurement tools, placements, and icons can all be configured, which offers great flexibility to use with tabbed
 * interfaces or other customized UI.
 *
 * How distances, areas, and perimeters are computed depends on the view type and its spatial reference.
 *
 * In 2D Maps:
 * - In geographic coordinate systems (GCS) and in Web Mercator, they are computed geodetically.
 * - In projected coordinate systems (PCS), apart from Web Mercator, they are computed
 *   in a Euclidean manner (in their respective PCS).
 *
 * In 3D Scenes:
 * - In geographic coordinate systems (GCS) and in Web Mercator:
 *   - horizontal distance is computed geodetically;
 *   - vertical distance is computed as a difference in z-values;
 *   - direct distance is computed in a Euclidean manner;
 *   - area and perimeter are computed:
 *     - in a Euclidean manner if the perimeter is below 100km;
 *     - geodetically if the perimeter is above 100km.
 * - In projected coordinate systems (PCS), apart from Web Mercator:
 *   - all three distances (direct, horizontal, and vertical), areas, and perimeters are computed in a Euclidean manner (in their respective PCS).
 *
 * @internal
 * @since 5.0
 * @example
 * ```html
 * <arcgis-map basemap="hybrid" center="-71.69,43.76" zoom="15">
 *   <arcgis-measurement slot="top-right" active-tool="distance"></arcgis-measurement>
 * </arcgis-map>
 * <script type="module">
 *   // Add the measurement component to the upper right hand corner
 *   // with the distance tool active
 *   const mapElement = document.querySelector("arcgis-map");
 *   const measurementElement = document.querySelector("arcgis-measurement");
 *
 *   // Switch between area and distance measurement
 *   function switchTool() {
 *     const tool = measurementElement.activeTool === "distance" ? "area" : "distance";
 *     measurementElement.activeTool = tool;
 *   }
 * </script>
 * ```
 */
export abstract class ArcgisMeasurement extends LitElement {
  /**
   * Specifies the current measurement tool to display. Setting its value to `area` activates
   * the area measurement tool and it works in both [arcgis-map](https://developers.arcgis.com/javascript/latest/references/map-components/components/arcgis-map/) and [arcgis-scene](https://developers.arcgis.com/javascript/latest/references/map-components/components/arcgis-scene/). To measure distance in an [arcgis-map](https://developers.arcgis.com/javascript/latest/references/map-components/components/arcgis-map/),
   * set the property to `distance` and in an [arcgis-scene](https://developers.arcgis.com/javascript/latest/references/map-components/components/arcgis-scene/) set it to `direct-line`.
   * If this property is not set, the component will not be displayed.
   *
   * @example
   * ```js
   * // To use the Measurement component with SceneView's direct-line tool active.
   * const measurementElement = document.querySelector("arcgis-measurement");
   * measurementElement.activeTool = "direct-line";
   *
   * // To switch between direct line and area measurement tools
   * function switchTool() {
   *   const tool = measurementElement.activeTool === "direct-line" ? "area" : "direct-line";
   *   measurementElement.activeTool = tool;
   * }
   * ```
   */
  accessor activeTool: MeasurementComponentType | null | undefined;
  /**
   * The measurement component that is currently being used. Use this property to
   * get access to the active component.
   *
   * @example
   * ```js
   * // Print the active widget to the console.
   * const measurementElement = document.querySelector("arcgis-measurement");
   * measurementElement.activeTool = "distance";
   * console.log("Active Widget: ", measurementElement.activeWidget);
   * ```
   */
  get activeWidget(): MeasurementWidget | null | undefined;
  /**
   * Unit system (imperial, metric) or specific unit used for displaying the area values.
   *
   * @example
   * ```js
   * // To use the Measurement component to display area in square US feet
   * const measurementElement = document.querySelector("arcgis-measurement");
   * measurementElement.activeTool = "area";
   * measurementElement.areaUnit = "square-us-feet";
   *
   * // To display the current area measurement unit
   * console.log("Current unit: ", measurement.areaUnit);
   * ```
   */
  accessor areaUnit: SystemOrAreaUnit;
  /**
   * If true, the component will not be destroyed automatically when it is
   * disconnected from the document. This is useful when you want to move the
   * component to a different place on the page, or temporarily hide it. If this
   * is set, make sure to call the [destroy()](https://developers.arcgis.com/javascript/latest/references/map-components/components/arcgis-measurement/#destroy) method when you are done to
   * prevent memory leaks.
   *
   * @default false
   */
  accessor autoDestroyDisabled: boolean;
  /**
   * Icon which represents the component.
   * Typically used when the component is controlled by another component (e.g. by the Expand component).
   *
   * @default "measure"
   * @see [Calcite Icons](https://developers.arcgis.com/calcite-design-system/icons/)
   */
  get icon(): Icon["icon"];
  set icon(value: IconName);
  /** The component's default label. */
  accessor label: string;
  /**
   * Unit system (imperial, metric) or specific unit used for displaying the distance values.
   *
   * @example
   * ```js
   * // To use the Measurement component to display distance in yards
   * const measurementElement = document.querySelector("arcgis-measurement");
   * measurementElement.activeTool = "distance";
   * measurementElement.linearUnit = "yards";
   *
   * // To display the current linear measurement unit
   * console.log("Current linear unit: ", measurementElement.linearUnit);
   * ```
   */
  accessor linearUnit: SystemOrLengthUnit;
  /**
   * By assigning the `id` attribute of the Map or Scene component to this property, you can position a child component anywhere in the DOM while still maintaining a connection to the Map or Scene.
   *
   * @see [Associate components with a Map or Scene component](https://developers.arcgis.com/javascript/latest/programming-patterns/#associate-components-with-a-map-or-scene-component)
   */
  accessor referenceElement: ArcgisReferenceElement | string | undefined;
  /**
   * The current state of the component.
   *
   * @default "disabled"
   * @example
   * ```js
   * // To display the state of the AreaMeasurement2D component
   * const measurementElement = document.querySelector("arcgis-measurement");
   * measurementElement.activeTool = "area";
   *
   * measurementElement.addEventListener("arcgisPropertyChange", () => {
   *   console.log("Current state: ", measurementElement.viewModel.state);
   * });
   * ```
   */
  get state(): MeasurementState;
  /**
   * The view associated with the component. 
   *   > **Note:** The recommended approach is to fully migrate applications to use map and scene components and avoid using MapView and SceneView directly. However, if you are migrating a large application from widgets to components, you might prefer a more gradual transition. To support this use case, the SDK includes this `view` property which connects a component to a MapView or SceneView. Ultimately, once migration is complete, the arcgis-measurement component will be associated with a map or scene component rather than using the `view` property.
   */
  accessor view: MapViewOrSceneView | null | undefined;
  /** Removes all measurement widgets and associated graphics. */
  clear(): Promise<void>;
  /** Permanently destroy the component. */
  destroy(): Promise<void>;
  /**
   * Starts a new measurement for the active measurement widget.
   *
   * @example
   * ```js
   * const measurementElement = document.querySelector("arcgis-measurement");
   * measurementElement.activeTool = "distance";
   *
   * function measure() {
   *   measurementElement.startMeasurement();
   * }
   *
   * measure();
   * ```
   */
  startMeasurement(): Promise<void>;
  "@setterTypes": {
    icon?: IconName;
  };
  /** Emitted when the value of a property is changed. Use this to listen to changes to properties. */
  readonly arcgisPropertyChange: import("@arcgis/lumina").TargetedEvent<this, { name: "activeTool" | "state"; }>;
  /** Emitted when the component associated with a map or scene view is ready to be interacted with. */
  readonly arcgisReady: import("@arcgis/lumina").TargetedEvent<this, void>;
  readonly "@eventTypes": {
    arcgisPropertyChange: ArcgisMeasurement["arcgisPropertyChange"]["detail"];
    arcgisReady: ArcgisMeasurement["arcgisReady"]["detail"];
  };
}