/// <reference path="../../index.d.ts" />
import type SceneView from "@arcgis/core/views/SceneView.js";
import type SliceAnalysis from "@arcgis/core/analysis/SliceAnalysis.js";
import type Collection from "@arcgis/core/core/Collection.js";
import type SlicePlane from "@arcgis/core/analysis/SlicePlane.js";
import type { PublicLitElement as LitElement } from "@arcgis/lumina";
import type { ArcgisReferenceElement, HeadingLevel } from "../types.js";
import type { SliceableLayer } from "./types.js";
import type { T9nMeta } from "@arcgis/lumina/controllers";
import type { Icon as Icon } from "@esri/calcite-components/components/calcite-icon";

/**
 * The Slice component is a 3D analysis tool that can be used to reveal occluded content in a
 * [arcgis-scene](https://developers.arcgis.com/javascript/latest/references/map-components/components/arcgis-scene/). It applies
 * [slice analysis](https://developers.arcgis.com/javascript/latest/references/core/analysis/SliceAnalysis/)
 * to any layer type, making it possible to see inside buildings or to explore geological surfaces.
 *
 * <a href="https://developers.arcgis.com/javascript/latest/sample-code/building-scene-layer-slice/index.html"><video src="https://developers.arcgis.com/javascript/latest/assets/references/core/widgets/slice.webm" autoplay loop muted playsinline></video></a>
 *
 * The slicing [shape](https://developers.arcgis.com/javascript/latest/references/map-components/components/arcgis-slice/#shape)
 * is always a [plane](https://developers.arcgis.com/javascript/latest/references/core/analysis/SlicePlane/).
 * By default, the plane is either horizontal or vertical. To allow a tilt angle for the plane, set
 * [tiltEnabled](https://developers.arcgis.com/javascript/latest/references/map-components/components/arcgis-slice/#tiltEnabled)
 * to `true`. The slice hides any content in front of the surface. The handles on the sides of the plane can be used to adjust
 * the size, heading, tilt, and position of the slice plane.
 * The [SlicePlane](https://developers.arcgis.com/javascript/latest/references/core/analysis/SlicePlane/)
 * can be set or retrieved using the [shape](https://developers.arcgis.com/javascript/latest/references/map-components/components/arcgis-slice/#shape) property.
 *
 * Once the slice plane is applied, layers can be excluded from the slicing. For example, by excluding the sublayers which include
 * columns and floor slabs, the inner structure of a building can investigated.
 *
 * [![slice-exclude](https://developers.arcgis.com/javascript/latest/assets/references/core/widgets/slice-exclude.avif)](https://developers.arcgis.com/javascript/latest/sample-code/building-scene-layer-slice/index.html)
 *
 * Holding the `Shift` key while placing a new slice applies it vertically.
 *
 * **Known limitation**
 *
 * Slice is only supported in a 3D [arcgis-scene](https://developers.arcgis.com/javascript/latest/references/map-components/components/arcgis-scene/) component.
 *
 * **See also**
 *
 * - [SliceAnalysis](https://developers.arcgis.com/javascript/latest/references/core/analysis/SliceAnalysis/)
 * - [Sample - BuildingSceneLayer with Slice component](https://developers.arcgis.com/javascript/latest/sample-code/building-scene-layer-slice/)
 * - [Sample - Analysis objects](https://developers.arcgis.com/javascript/latest/sample-code/analysis-objects/)
 */
export abstract class ArcgisSlice extends LitElement {
  /** @internal */
  protected _messages: Partial<{
      componentLabel: string;
      cancel: string;
      hint: string;
      voxelHint: string;
      excludeHint: string;
      verticalHint: string;
      verticalHint2: string;
      unsupported: string;
      multipleDisabled: string;
      newSlice: string;
      excludedLayers: string;
      pickLayer: string;
      excludeLayer: string;
      includeLayer: string;
      ground: string;
  }> & T9nMeta<{
      componentLabel: string;
      cancel: string;
      hint: string;
      voxelHint: string;
      excludeHint: string;
      verticalHint: string;
      verticalHint2: string;
      unsupported: string;
      multipleDisabled: string;
      newSlice: string;
      excludedLayers: string;
      pickLayer: string;
      excludeLayer: string;
      includeLayer: string;
      ground: string;
  }>;
  /**
   * The [SliceAnalysis](https://developers.arcgis.com/javascript/latest/references/core/analysis/SliceAnalysis/)
   * created or modified by the component.
   *
   * When connecting the Slice component to the [arcgis-scene](https://developers.arcgis.com/javascript/latest/references/map-components/components/arcgis-scene/)
   * component, it automatically creates an empty analysis and adds it to the Scene's
   * [arcgis-scene.analyses](https://developers.arcgis.com/javascript/latest/references/map-components/components/arcgis-scene/#analyses) collection.
   * You can then wait for the [SliceAnalysisView3D](https://developers.arcgis.com/javascript/latest/references/core/views/3d/analysis/SliceAnalysisView3D/)
   * to be created before interacting with the slice or reading the current slice parameters.
   *
   * ```js
   * // Get the Scene component and the Slice component, and wait until both are ready.
   * const viewElement = document.querySelector("arcgis-scene");
   * await viewElement.viewOnReady();
   * const sliceElement = document.querySelector("arcgis-slice");
   * await sliceElement.componentOnReady();
   *
   * // Get the SliceAnalysis created by the Slice component.
   * const analysis = sliceElement.analysis;
   *
   * // Get the SliceAnalysisView3D and watch for changes.
   * const analysisView = await viewElement.whenAnalysisView(analysis);
   * const handle = reactiveUtils.watch(
   *   () => analysis.shape,
   *   () => {
   *     console.log("Slice active:", analysisView.active);
   *     console.log("Slice interactive:", analysisView.interactive);
   *     console.log("Slice shape:", analysis.shape);
   *   },
   * );
   * ```
   * Whenever the component is destroyed, the analysis is automatically removed from the collection.
   *
   * Alternatively, a programmatically created [SliceAnalysis](https://developers.arcgis.com/javascript/latest/references/core/analysis/SliceAnalysis/)
   * can be provided to the component.
   * Then, the application itself needs to add it to and later remove it from the analyses collection of the Scene component.
   *
   * ```js
   * // Create the SliceAnalysis.
   * const sliceAnalysis = new SliceAnalysis({
   *    shape: new SlicePlane({
   *      position: new Point({
   *        spatialReference: { latestWkid: 3857, wkid: 102100 },
   *        x: -13624925.727820931,
   *        y: 4550341.695170021,
   *        z: 56
   *      }),
   *      tilt: 270,
   *      width: 310,
   *      height: 190,
   *      heading: 45
   *    })
   * });
   * // Get the Scene component and the Slice component, and wait until both are ready.
   * const viewElement = document.querySelector("arcgis-scene");
   * await viewElement.viewOnReady();
   * const sliceElement = document.querySelector("arcgis-slice");
   * await sliceElement.componentOnReady();
   *
   * // Add the analysis to the analyses collection of the Scene component.
   * viewElement.analyses.add(sliceAnalysis);
   *
   * // Connect the analysis to the slice component:
   * sliceElement.analysis = sliceAnalysis;
   * ```
   */
  accessor analysis: SliceAnalysis;
  /**
   * 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-slice/#destroy) method when you are done to
   * prevent memory leaks.
   *
   * @default false
   */
  accessor autoDestroyDisabled: boolean;
  /**
   * Add layers to this collection to exclude them from the slice. Layers that
   * are draped on the ground surface are not affected by this property
   */
  accessor excludedLayers: Collection<SliceableLayer>;
  /**
   * Indicates whether the [Ground](https://developers.arcgis.com/javascript/latest/references/core/Ground/) and layers that
   * are draped on the ground surface are excluded from the slice.
   *
   * @default false
   */
  accessor excludeGroundSurface: boolean;
  /**
   * Indicates the heading level to use for the "Excluded layers" heading.
   *
   * @default 3
   */
  accessor headingLevel: HeadingLevel;
  /**
   * If true, the button that starts a new slice will be hidden.
   *
   * @default false
   * @since 5.0
   */
  accessor hideStartButton: boolean;
  /**
   * Indicates whether the component's visualization is hidden in the view.
   *
   * @default false
   * @since 5.0
   */
  accessor hideVisualization: boolean;
  /**
   * Icon which represents the component.
   * Typically used when the component is controlled by another component (e.g. by the Expand component).
   *
   * @default "slice"
   * @see [Calcite Icons](https://developers.arcgis.com/calcite-design-system/icons/)
   */
  accessor icon: Icon["icon"] | undefined;
  /** The component's default label. */
  accessor label: string | undefined;
  /**
   * Replace localized message strings with your own strings.
   *
   * _**Note**: Individual message keys may change between releases._
   */
  accessor messageOverrides: {
      componentLabel?: string | undefined;
      cancel?: string | undefined;
      hint?: string | undefined;
      voxelHint?: string | undefined;
      excludeHint?: string | undefined;
      verticalHint?: string | undefined;
      verticalHint2?: string | undefined;
      unsupported?: string | undefined;
      multipleDisabled?: string | undefined;
      newSlice?: string | undefined;
      excludedLayers?: string | undefined;
      pickLayer?: string | undefined;
      excludeLayer?: string | undefined;
      includeLayer?: string | undefined;
      ground?: string | undefined;
  };
  /**
   * 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 shape used to slice elements in a 3D scene. Currently the only supported shape is a
   * [plane](https://developers.arcgis.com/javascript/latest/references/core/analysis/SlicePlane/).
   *
   * @since 4.28
   * @example
   * ```js
   * // Create a slice plane programmatically.
   * const shape = new SlicePlane({
   *   position: new Point({
   *      spatialReference: { latestWkid: 3857, wkid: 102100 },
   *      x: -13624925.727820931,
   *      y: 4550341.695170021,
   *      z: 56
   *   }),
   *   tilt: 270,
   *   width: 310,
   *   height: 190,
   *   heading: 45
   * });
   * // Apply the new shape to the slice component's shape.
   * slice.shape = shape;
   * ```
   * @example
   * ```js
   * // Clone the shape to modify its properties.
   * const shape = slice.shape.clone();
   * // Set new values for heading and tilt.
   * shape.heading = 180;
   * shape.tilt = 45;
   * // Apply the new shape to the slice component's shape.
   * slice.shape = shape;
   * ```
   */
  accessor shape: SlicePlane | null | undefined;
  /**
   * The component's state. The values mean the following:
   *
   * * `disabled` - not ready yet
   * * `excludingLayer` - currently excluding a layer from the slice
   * * `ready` - ready for slicing
   * * `slicing` - currently slicing
   * * `sliced` - finished slicing and a valid shape is available
   */
  get state(): "disabled" | "ready" | "excludingLayer" | "sliced" | "slicing";
  /**
   * Enable tilting the slice shape. If set to true, the slice shape will orient itself as best as
   * possible to the surface under the cursor when first placing the shape. If set to false, the slice shape is
   * restricted to be either horizontal or vertical.
   *
   * @default false
   */
  accessor tiltEnabled: boolean;
  /**
   * 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-slice component will be associated with a map or scene component rather than using the `view` property.
   */
  accessor view: SceneView | undefined;
  /**
   * Clear the [shape](https://developers.arcgis.com/javascript/latest/references/map-components/components/arcgis-slice/#shape) of the slice, effectively removing it from the view. Other properties like [excludedLayers](https://developers.arcgis.com/javascript/latest/references/map-components/components/arcgis-slice/#excludedLayers)
   * and [excludeGroundSurface](https://developers.arcgis.com/javascript/latest/references/map-components/components/arcgis-slice/#excludeGroundSurface) are not modified.
   * Calling this method changes the [state](https://developers.arcgis.com/javascript/latest/references/map-components/components/arcgis-slice/#state) to `ready`.
   */
  clear(): Promise<void>;
  /** Permanently destroy the component. */
  destroy(): Promise<void>;
  /**
   * Start the interactive placement of a new slice, clearing the previous [shape](https://developers.arcgis.com/javascript/latest/references/map-components/components/arcgis-slice/#shape).
   * Calling this method changes the [state](https://developers.arcgis.com/javascript/latest/references/map-components/components/arcgis-slice/#state) to `slicing`.
   */
  start(): Promise<void>;
  /** 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: "analysis" | "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: ArcgisSlice["arcgisPropertyChange"]["detail"];
    arcgisReady: ArcgisSlice["arcgisReady"]["detail"];
  };
}