import type Camera from "../Camera.js";
import type Graphic from "../Graphic.js";
import type Ground from "../Ground.js";
import type Viewpoint from "../Viewpoint.js";
import type Analysis from "../analysis/Analysis.js";
import type Collection from "../core/Collection.js";
import type Point from "../geometry/Point.js";
import type Layer from "../layers/Layer.js";
import type MediaLayer from "../layers/MediaLayer.js";
import type RouteLayer from "../layers/RouteLayer.js";
import type BuildingSublayer from "../layers/buildingSublayers/BuildingSublayer.js";
import type SubtypeSublayer from "../layers/support/SubtypeSublayer.js";
import type { ReadonlyArrayOrCollection } from "../core/Collection.js";
import type { AbortOptions } from "../core/promiseUtils.js";
import type { ScreenPoint } from "../core/types.js";
import type { GeometryUnion } from "../geometry/types.js";
import type { MediaElement } from "../layers/support/media.js";
import type { NetworkFeature } from "../rest/support/types.js";
import type { AnalysisViewUnion } from "./analysis/types.js";
import type { EasingName } from "./animation/types.js";
import type { ViewEventTypes } from "./input/types.js";

export type ObjectId = number | string;

export type HighlightTarget = Graphic | Graphic[] | Collection<Graphic>;

export interface SingleBandPixelHighlightTarget {}

export interface XYBandPixelHighlightTarget {}

export type PixelHighlightTarget = SingleBandPixelHighlightTarget | XYBandPixelHighlightTarget;

export type TargetBase = number[] | GeometryUnion | GeometryUnion[] | Graphic | Graphic[] | Viewpoint;

export type Target2D = TargetBase;

export type Target3D = TargetBase | Camera;

export interface TargetOptionsBase {
  /** The [MapView#scale](https://developers.arcgis.com/javascript/latest/api-reference/esri-views-MapView.html#scale)/[SceneView#scale](https://developers.arcgis.com/javascript/latest/api-reference/esri-views-SceneView.html#scale) to go to. */
  scale?: number;
  /** The final [MapView#zoom](https://developers.arcgis.com/javascript/latest/api-reference/esri-views-MapView.html#zoom)/[SceneView#zoom](https://developers.arcgis.com/javascript/latest/api-reference/esri-views-SceneView.html#zoom) value to go to. */
  zoom?: number;
}

export interface TargetOptions2DBase extends TargetOptionsBase {}

export interface CenterOptions2D extends TargetOptions2DBase {
  /** The [MapView#center](https://developers.arcgis.com/javascript/latest/api-reference/esri-views-MapView.html#center) to go to. */
  center?: number[] | Point;
}

export interface TargetOptions2D extends TargetOptions2DBase {
  /** The target of the animation. */
  target?: Target2D;
}

export interface TargetOptions3DBase extends TargetOptionsBase {}

export interface CenterOptions3D extends TargetOptions3DBase {
  /** The [SceneView#center](https://developers.arcgis.com/javascript/latest/api-reference/esri-views-SceneView.html#center) to go to. */
  center?: number[] | Point;
}

export interface TargetOptions3D extends TargetOptions3DBase {
  /** The target of the animation. */
  target?: Target3D;
}

/**
 * The target location/viewpoint to animate to in the [MapView#goTo()](https://developers.arcgis.com/javascript/latest/api-reference/esri-views-MapView.html#goTo) method.
 * A two-element array of numbers represents the [x,y] coordinates to center the view on.
 * When using an object for the `target`, use the properties
 * in the table below.
 */
export type GoToTarget2D = TargetOptions2D | CenterOptions2D | Target2D;

/**
 * The target location/viewpoint to animate to in the [SceneView#goTo()](https://developers.arcgis.com/javascript/latest/api-reference/esri-views-SceneView.html#goTo) method.
 * A two or three-element array of numbers represents the [x,y,z] coordinates to center the view on.
 * When using an object for the `target`, use the properties
 * in the table below.
 */
export type GoToTarget3D = TargetOptions3D | CenterOptions3D | Target3D;

/**
 * User provided easing function. The function receives a normalized time between 0 and
 * 1 as input and should provide a transformed normalized time between 0 and 1 as output.
 *
 * @param t - The input time (from 0 to 1)
 * @param duration - The total duration (in milliseconds) of the animation. This may
 *   be used for heuristics on deciding what type of easing to perform.
 * @returns a value between 0 and 1
 * @example
 * // Simple quadratic ease in function
 * function easeIn(t) {
 *   return t * t;
 * }
 */
export type EasingFunction = (t: number, duration: number) => number;

export type AnimationMode = "always" | "auto";

export interface GoToOptionsBase extends AbortOptions {
  /**
   * Indicates whether the transition to the new viewpoint is animated. If set to false, `speedFactor`, `duration`, `maxDuration`, and `easing` properties are ignored.
   * > [!WARNING]
   * >
   * >   Starting at 4.30, the default behavior of `goTo()` follows the user preference for [reduced motion](https://developers.arcgis.com/javascript/latest/accessibility/#reduced-motion).
   * >   By default, `goTo()` will animate, but when the user expresses a preference for reduced motion, `goTo()` will navigate to the specified target without animation.
   * >   It is possible to override the user's preference for reduced motion by configuring [esriConfig.respectPrefersReducedMotion](https://developers.arcgis.com/javascript/latest/api-reference/esri-config.html#ConfigWithRespectPrefersReducedMotion)
   * >   or on a per-call basis by specifying the `animate` property.
   *
   * @default true
   */
  animate?: boolean;
  /**
   * Set the exact duration (in milliseconds) of the animation. Note that by default, animation
   *   duration is calculated based on the time required to reach the target at a constant speed. Setting duration
   *   overrides the speedFactor option. Note that the resulting duration is still limited to the maxDuration.
   */
  duration?: number | null;
  /**
   * The easing function to use for
   *   the animation. This may either be a preset (named) function, or a user specified function. Supported named presets are:
   *     `linear`, `cubic-in`, `cubic-out`, `cubic-in-out`,
   *     `expo-in`, `expo-out`, `expo-in-out`, `quad-in-out-coast`,
   *     `ease-in`, `ease-out`, `ease-in-out`, as well as
   *     `in-cubic`, `out-cubic`, `in-out-cubic`,
   *     `in-expo`, `out-expo`, `in-out-expo`, and `in-out-coast-quad`.
   *   See [easing functions](https://easings.net/) and [CSS easing functions](https://developer.mozilla.org/en-US/docs/Web/CSS/easing-function#ease) for graphical representations of these functions.
   *
   * By default, animations that are less than 1000 ms use the `expo-out` easing function; longer animations use the `quad-in-out-coast` easing function.
   *
   * > [!WARNING]
   * >
   * > The following prenamed easing functions have been deprecated since version 4.33: `in-cubic`, `out-cubic`, `in-out-cubic`,
   * > `in-expo`, `out-expo`, `in-out-expo`, and `in-out-coast-quad`. Please use `cubic-in`, `cubic-out`, `cubic-in-out`,
   * > `expo-in`, `expo-out`, `expo-in-out`, and `quad-in-out-coast` instead.
   *
   * @default ease
   */
  easing?: EasingName | EasingFunction;
  /**
   * The maximum allowed duration (in milliseconds) of the animation. The
   *   default maxDuration value takes the specified speedFactor into account. If animationMode is set to "always",
   *   animations will be sped up to fit in this time. Otherwise, animations will not run if they exceed this time.
   *
   * @default isMapView ? 4000 : 8000
   */
  maxDuration?: number;
  /**
   * Increases or decreases the animation speed by the specified factor. A speedFactor
   *   of 2 will make the animation twice as fast, while a speedFactor of 0.5 will make the animation half as fast. Setting
   *   the speed factor will automatically adapt the default maxDuration accordingly.
   *
   * @default 1
   */
  speedFactor?: number;
}

/** Animation options for the [MapView#goTo()](https://developers.arcgis.com/javascript/latest/api-reference/esri-views-MapView.html#goTo) method. See properties below for object specifications. */
export interface GoToOptions2D extends GoToOptionsBase {
  /**
   * **Since 4.30.** The strategy for deciding whether the transition will animate when `animate` is not `false`, and the user has not expressed a preference for reduced motion.
   *   If set to `"auto"`, the view will automatically decide whether or not to animate, depending on an internal heuristic that considers time, distance, and the `maxDuration` option.
   *   If set to `"always"`, the transition will always animate.
   *
   * @default auto
   */
  animationMode?: AnimationMode;
  /**
   * **Since 4.28.** Indicates if the target geometry is normalized based on the [MapView#center](https://developers.arcgis.com/javascript/latest/api-reference/esri-views-MapView.html#center) of the view.
   * When `true`, if the user pans more than 270 degrees east, the `goTo()` method will navigate the view 90 degrees west when panning to the designated target.
   * This property is only honored if [MapView.spatialReference.isWrappable](https://developers.arcgis.com/javascript/latest/api-reference/esri-geometry-SpatialReference.html#isWrappable) is `true`.
   *
   * @default true
   */
  pickClosestTarget?: boolean;
}

/** Animation options for the [SceneView#goTo()](https://developers.arcgis.com/javascript/latest/api-reference/esri-views-SceneView.html#goTo) method. See properties below for parameter specifications. */
export interface GoToOptions3D extends GoToOptionsBase {}

/** Options for the [MapView#toScreen()](https://developers.arcgis.com/javascript/latest/api-reference/esri-views-MapView.html#toScreen) method. See properties below for object specifications. */
export interface ToScreenOptions2D {
  /**
   * Indicates if the point will be normalized based on the [MapView#center](https://developers.arcgis.com/javascript/latest/api-reference/esri-views-MapView.html#center) of the view.
   * When `true`, if the point is not in view, the result of toScreen() will not exceed the pixel equivalent of 180 degrees east or west of the center of the view.
   * This property is only honored if [MapView.spatialReference.isWrappable](https://developers.arcgis.com/javascript/latest/api-reference/esri-geometry-SpatialReference.html#isWrappable) is `true`.
   *
   * @default true
   */
  pickClosestTarget?: boolean;
}

/** The resulting features returned from the [Popup#fetchFeatures()](https://developers.arcgis.com/javascript/latest/api-reference/esri-widgets-Popup.html#fetchFeatures) method. */
export interface FetchPopupFeaturesResult {
  /** A promise containing [graphics](https://developers.arcgis.com/javascript/latest/api-reference/esri-Graphic.html) from the selected location. This can be a combination of graphics derived from a [LayerView](https://developers.arcgis.com/javascript/latest/api-reference/esri-views-layers-LayerView.html), and/or [graphics](https://developers.arcgis.com/javascript/latest/api-reference/esri-Graphic.html) that reside directly on the view, ie. [View#graphics](https://developers.arcgis.com/javascript/latest/api-reference/esri-views-View.html#graphics). */
  allGraphicsPromise: Promise<Graphic[]>;
  /** The resulting location of the [MapView#hitTest()](https://developers.arcgis.com/javascript/latest/api-reference/esri-views-MapView.html#hitTest) or [SceneView#hitTest()](https://developers.arcgis.com/javascript/latest/api-reference/esri-views-SceneView.html#hitTest)'s' `hitTest`. */
  location?: Point | null;
  /** An array of promises containing [graphics](https://developers.arcgis.com/javascript/latest/api-reference/esri-Graphic.html) from the selected location. Each promise resolves to an array of graphics. */
  pendingFeatures: Promise<Graphic[]>[];
}

/**
 * Object specification for the result returned in [ViewHitTestResult](https://developers.arcgis.com/javascript/latest/api-reference/esri-views-types.html#ViewHitTestResult) of the [MapView#hitTest()](https://developers.arcgis.com/javascript/latest/api-reference/esri-views-MapView.html#hitTest) method.
 *
 * @since 4.24
 */
export type ViewHit = GraphicHit | MediaHit | RouteHit;

/**
 * Object specification for the graphic hit result returned in [ViewHitTestResult](https://developers.arcgis.com/javascript/latest/api-reference/esri-views-types.html#ViewHitTestResult) of the [MapView#hitTest()](https://developers.arcgis.com/javascript/latest/api-reference/esri-views-MapView.html#hitTest) method.
 * See the table below for the specification of each property in this object.
 *
 * @since 4.24
 */
export interface GraphicHit {
  /**
   * A graphic present in the view that intersects the input screen coordinates. If a label intersects the input screen coordinates (since 4.11), the corresponding graphic is returned. If the graphic comes from a layer with an applied [Renderer](https://developers.arcgis.com/javascript/latest/api-reference/esri-renderers-Renderer.html), then the [symbol](https://developers.arcgis.com/javascript/latest/api-reference/esri-Graphic.html#symbol) property will be empty. Other properties may be empty based on the context in which the graphic is fetched.
   *
   * Some layers do not have a [graphic.geometry](https://developers.arcgis.com/javascript/latest/api-reference/esri-Graphic.html#geometry) (for example: [VoxelLayer](https://developers.arcgis.com/javascript/latest/api-reference/esri-layers-VoxelLayer.html)). The [graphic.attributes](https://developers.arcgis.com/javascript/latest/api-reference/esri-Graphic.html#attributes) only includes attributes which are loaded by the client, so it can be a subset of all attributes. [FeatureLayer.outFields](https://developers.arcgis.com/javascript/latest/api-reference/esri-layers-FeatureLayer.html#outFields) with `["*"]` can be used to force all attributes to be present.
   *
   * The [graphic.symbol](https://developers.arcgis.com/javascript/latest/api-reference/esri-Graphic.html#symbol) exists only for graphics coming from [GraphicsLayer](https://developers.arcgis.com/javascript/latest/api-reference/esri-layers-GraphicsLayer.html) or [view.graphics](https://developers.arcgis.com/javascript/latest/api-reference/esri-views-View.html#graphics), but it is possible to compute the displayed symbology with [getDisplayedSymbol](https://developers.arcgis.com/javascript/latest/api-reference/esri-symbols-support-symbolUtils.html#getDisplayedSymbol).
   *
   * If the result comes from a [VectorTileLayer](https://developers.arcgis.com/javascript/latest/api-reference/esri-layers-VectorTileLayer.html), result graphics contain attributes of style layers. The graphic's [origin](https://developers.arcgis.com/javascript/latest/api-reference/esri-Graphic.html#origin) property contains `layerId` and `layerIndex` information, corresponding to the unique id and index of the style layer in the [vector tile style](https://developers.arcgis.com/rest/services-reference/vector-tile-style.htm). Spatial information about the actual feature represented in the style layer is returned only if the style layer is a [symbol layer](https://maplibre.org/maplibre-style-spec/layers/#symbol); otherwise, the graphic's geometry is `null`.
   */
  graphic: Graphic;
  /** The layer that contains the feature/graphic. */
  layer: Layer;
  /** The point geometry in the spatial reference of the view corresponding with the input screen coordinates. */
  mapPoint?: Point | null;
  type: "graphic";
}

/**
 * Object specification for the media hit results returned from [MediaLayer](https://developers.arcgis.com/javascript/latest/api-reference/esri-layers-MediaLayer.html) in [ViewHitTestResult](https://developers.arcgis.com/javascript/latest/api-reference/esri-views-types.html#ViewHitTestResult) of the [MapView#hitTest()](https://developers.arcgis.com/javascript/latest/api-reference/esri-views-MapView.html#hitTest) method.
 * See the table below for the specification of each property in this object.
 *
 * @since 4.24
 */
export interface MediaHit {
  /**
   * An element representing a media element in [MediaLayer#source](https://developers.arcgis.com/javascript/latest/api-reference/esri-layers-MediaLayer.html#source)
   * that intersects the input screen coordinates.
   */
  element: MediaElement;
  /** The media layer that contains the element. */
  layer: MediaLayer;
  /** The point geometry in the spatial reference of the view corresponding with the input screen coordinates. */
  mapPoint?: Point | null;
  /** _Since 4.28_ An object representing a point on the element. The origin (0, 0) corresponds to the top-left corner of the element. */
  sourcePoint?: ScreenPoint | null;
  type: "media";
}

/**
 * Object specification for the route hit results returned from [RouteLayer](https://developers.arcgis.com/javascript/latest/api-reference/esri-layers-RouteLayer.html) in [ViewHitTestResult](https://developers.arcgis.com/javascript/latest/api-reference/esri-views-types.html#ViewHitTestResult) of the [MapView#hitTest()](https://developers.arcgis.com/javascript/latest/api-reference/esri-views-MapView.html#hitTest) method.
 * See the table below for the specification of each property in this object.
 *
 * @since 4.24
 */
export interface RouteHit {
  /** The route layer that contains the element. */
  layer: RouteLayer;
  /** The point geometry in the spatial reference of the view corresponding with the input screen coordinates. */
  mapPoint: Point;
  /** The route hit test will contain all intersecting network elements which, includes one of the following: DirectionLine, DirectionPoint, PointBarrier, PolylineBarrier, PolygonBarrier, Stop, or RouteInfo. */
  networkFeature: NetworkFeature;
  type: "route";
}

/**
 * Object specification for the result of the [MapView#hitTest()](https://developers.arcgis.com/javascript/latest/api-reference/esri-views-MapView.html#hitTest) method.
 *
 * @since 4.24
 */
export interface ViewHitTestResult {
  /**
   * An array of result objects returned from the [MapView#hitTest()](https://developers.arcgis.com/javascript/latest/api-reference/esri-views-MapView.html#hitTest).
   * Results are returned when the location of the input screen coordinates intersects a [Graphic](https://developers.arcgis.com/javascript/latest/api-reference/esri-Graphic.html),
   * [media element](https://developers.arcgis.com/javascript/latest/api-reference/esri-layers-support-ImageElement.html), or [RouteLayer](https://developers.arcgis.com/javascript/latest/api-reference/esri-layers-RouteLayer.html) in the view.
   */
  results: ViewHit[];
  /** The screen coordinates (or native mouse event) of the click on the view. */
  screenPoint: ScreenPoint;
}

/**
 * Object returned when [MapView#takeScreenshot()](https://developers.arcgis.com/javascript/latest/api-reference/esri-views-MapView.html#takeScreenshot) or [SceneView#takeScreenshot()](https://developers.arcgis.com/javascript/latest/api-reference/esri-views-SceneView.html#takeScreenshot) promise resolves:
 *
 * @since 4.9
 */
export interface Screenshot {
  /** The raw RGBA image data. */
  data: ImageData;
  /** A data url representing the screenshot. */
  dataUrl: string;
}

export interface EncodingSettings {
  /**
   * The format of the encoded image data. Defaults to png.
   *
   * @default png
   */
  format: "png" | "jpeg" | "jpg";
  /**
   * The quality (between 0 and 100) of the jpg encoded image data. Defaults to 90.
   *
   * @default 98
   */
  quality: number;
}

export interface SettingsCommon extends EncodingSettings {
  /**
   * Indicates whether to ignore the background
   *   color set in the [initial view properties](https://developers.arcgis.com/javascript/latest/api-reference/esri-WebMap.html#initialViewProperties) of the web map.
   *
   * @default false
   */
  ignoreBackground?: boolean;
}

export interface Rect {
  /** The height of the area. */
  height: number;
  /** The width of the area. */
  width: number;
  /** The x coordinate of the area. */
  x: number;
  /** The y coordinate of the area. */
  y: number;
}

/**
 * Param settings used to capture screenshots
 * area refer to the upper left corner of the readback area, where width and height designate the size of the area for reading
 * Width and height indicate the target image's width and height
 * Format indicate the output image format (PNG or JPEG) which quality indicate the compression level (and hence the quality of the resulting image)
 */
export interface UserSettings extends SettingsCommon {
  /**
   * Specifies whether to take a screenshot of a specific
   *   area of the view. The area coordinates are relative to the origin of the padded view (see
   *   [MapView#padding](https://developers.arcgis.com/javascript/latest/api-reference/esri-views-MapView.html#padding)/[SceneView#padding](https://developers.arcgis.com/javascript/latest/api-reference/esri-views-SceneView.html#padding)) and will be clipped to the
   *   view size. Defaults to the whole view (padding excluded).
   */
  area: Rect;
  /**
   * The height of the screenshot (defaults to the area height). The
   *   width will be derived automatically if left unspecified, according to the aspect ratio of the
   *   screenshot area.
   */
  height: number;
  /**
   * Indicates whether view padding should be ignored.
   *   Set this property to `true` to allow padded areas to be included in the screenshot.
   *
   * @default false
   */
  ignorePadding: boolean;
  /** An optional list of layers to be included in the screenshot. */
  layers?: ReadonlyArrayOrCollection<Layer>;
  /**
   * The width of the screenshot (defaults to the area width). The
   *   height will be derived automatically if left unspecified, according to the aspect ratio of the
   *   of the screenshot area.
   */
  width: number;
}

export type HitExtension<T> = T
  & {
  /** The distance from the camera position to the point geometry hit on this graphic. In global scenes the distance will be in meters while in local scenes the distance will be in the unit of the spatial reference of the view. */
  distance: number;
};

/**
 * Object specification for the result returned in {@link views/SceneViewHitTestResult!SceneViewHitTestResult} of the [SceneView#hitTest()](https://developers.arcgis.com/javascript/latest/api-reference/esri-views-SceneView.html#hitTest) method.
 *
 * @since 4.24
 */
export type SceneViewHit = SceneViewGraphicHit | SceneViewMediaHit | SceneViewRouteHit;

/**
 * Object specification for the graphic hit result returned in {@link views/SceneViewHitTestResult!SceneViewHitTestResult} of the [SceneView#hitTest()](https://developers.arcgis.com/javascript/latest/api-reference/esri-views-SceneView.html#hitTest) method.
 * See the table below for the specification of each property in this object.
 *
 * @since 4.24
 */
export type SceneViewGraphicHit = HitExtension<GraphicHit>;

/**
 * Object specification for the media hit results returned from [MediaLayer](https://developers.arcgis.com/javascript/latest/api-reference/esri-layers-MediaLayer.html) in {@link views/SceneViewHitTestResult!SceneViewHitTestResult} of the [SceneView#hitTest()](https://developers.arcgis.com/javascript/latest/api-reference/esri-views-SceneView.html#hitTest) method.
 * See the table below for the specification of each property in this object.
 *
 * @since 4.24
 */
export type SceneViewMediaHit = HitExtension<MediaHit>;

/**
 * Object specification for the route hit results returned from [RouteLayer](https://developers.arcgis.com/javascript/latest/api-reference/esri-layers-RouteLayer.html) in {@link views/SceneViewHitTestResult!SceneViewHitTestResult} of the [SceneView#hitTest()](https://developers.arcgis.com/javascript/latest/api-reference/esri-views-SceneView.html#hitTest) method.
 * See the table below for the specification of each property in this object.
 *
 * @since 4.24
 */
export type SceneViewRouteHit = HitExtension<RouteHit>;

/**
 * Object specification for the result of the [SceneView#hitTest()](https://developers.arcgis.com/javascript/latest/api-reference/esri-views-SceneView.html#hitTest) method.
 *
 * @since 4.24
 */
export interface SceneViewHitTestResult extends ViewHitTestResult {
  /** Ground intersection result. The ground hit result will always be returned, even if the ground was excluded from the [SceneView#hitTest()](https://developers.arcgis.com/javascript/latest/api-reference/esri-views-SceneView.html#hitTest). */
  ground: SceneViewHitTestResultGround;
  /**
   * An array of result objects returned from the [SceneView#hitTest()](https://developers.arcgis.com/javascript/latest/api-reference/esri-views-SceneView.html#hitTest)
   * when the location of the input screen coordinates intersect features in the view.
   */
  results: SceneViewHit[];
}

export interface SceneViewHitTestResultGround {
  /** The distance from camera position to the ground hit. The distance will be `0` if the ground was not hit at all. In global scenes the distance will be in meters while in local scenes the distance will be in the unit of the spatial reference of the view. */
  distance: number;
  /**
   * The point at which the ground was hit while performing the
   *   hitTest. This may be `null` when the ground was not hit at all (for example by clicking on the sky).
   */
  mapPoint: Point;
}

/**
 * A layer, graphic, or collection of layers or graphics to be used in the [MapView#hitTest()](https://developers.arcgis.com/javascript/latest/api-reference/esri-views-MapView.html#hitTest) filter options.
 *
 * @see [MapView#hitTest()](https://developers.arcgis.com/javascript/latest/api-reference/esri-views-MapView.html#hitTest)
 */
export type HitTestItem = Layer | SubtypeSublayer | Graphic;

export type HitTestOptionsItem = HitTestItem | Iterable<HitTestItem | Iterable<HitTestItem>>;

export interface HitTestOptions {
  /**
   * A list of layers and graphics to exclude from the hitTest. No layers or graphics will be
   *   excluded if exclude is not specified.
   */
  exclude?: HitTestOptionsItem | null;
  /**
   * A list of layers and graphics to include in the hitTest. All layers and graphics will be
   *   included if include is not specified.
   */
  include?: HitTestOptionsItem | null;
}

export type HitTestItem3D = HitTestItem | Ground | BuildingSublayer;

export type HitTestOptions3DItem = HitTestItem3D | Iterable<HitTestItem3D | Iterable<HitTestItem3D>>;

export interface HitTestOptions3D {
  /**
   * A list of layers and graphics to exclude for intersection testing. No layers or graphics
   *   will be excluded if exclude is not specified.
   */
  exclude?: HitTestOptions3DItem | null;
  /**
   * A list of layers and graphics to include for intersection testing. All layers and graphics
   *   will be included if include is not specified.
   */
  include?: HitTestOptions3DItem | null;
}

export interface Breakpoints {
  /**
   * Sets the `large` breakpoint in pixels used by
   * [widthBreakpoint](https://developers.arcgis.com/javascript/latest/api-reference/esri-views-BreakpointsOwner.html#widthBreakpoint) and [heightBreakpoint](https://developers.arcgis.com/javascript/latest/api-reference/esri-views-BreakpointsOwner.html#heightBreakpoint). If the
   * view's [height](https://developers.arcgis.com/javascript/latest/api-reference/esri-views-View2D.html#height) or [width](https://developers.arcgis.com/javascript/latest/api-reference/esri-views-View2D.html#width) is between this value and the value
   * of the `medium` property, then the value of
   * [widthBreakpoint](https://developers.arcgis.com/javascript/latest/api-reference/esri-views-BreakpointsOwner.html#widthBreakpoint) or [heightBreakpoint](https://developers.arcgis.com/javascript/latest/api-reference/esri-views-BreakpointsOwner.html#heightBreakpoint) will
   * be `large`.
   * [widthBreakpoint](https://developers.arcgis.com/javascript/latest/api-reference/esri-views-BreakpointsOwner.html#widthBreakpoint) and [heightBreakpoint](https://developers.arcgis.com/javascript/latest/api-reference/esri-views-BreakpointsOwner.html#heightBreakpoint). If the
   * view's [height](https://developers.arcgis.com/javascript/latest/api-reference/esri-views-View2D.html#height) or [width](https://developers.arcgis.com/javascript/latest/api-reference/esri-views-View2D.html#width) is greater than the value
   * of the `large` property, then the value of
   * [widthBreakpoint](https://developers.arcgis.com/javascript/latest/api-reference/esri-views-BreakpointsOwner.html#widthBreakpoint) or [heightBreakpoint](https://developers.arcgis.com/javascript/latest/api-reference/esri-views-BreakpointsOwner.html#heightBreakpoint) will
   * be `xlarge`.
   *
   * @default 1200
   */
  large: number;
  /**
   * Sets the `medium` breakpoint in pixels used by
   * [widthBreakpoint](https://developers.arcgis.com/javascript/latest/api-reference/esri-views-BreakpointsOwner.html#widthBreakpoint) and [heightBreakpoint](https://developers.arcgis.com/javascript/latest/api-reference/esri-views-BreakpointsOwner.html#heightBreakpoint). If the
   * view's [height](https://developers.arcgis.com/javascript/latest/api-reference/esri-views-View2D.html#height) or [width](https://developers.arcgis.com/javascript/latest/api-reference/esri-views-View2D.html#width) is between this value and the value
   * of the `small` property, then the value of
   * [widthBreakpoint](https://developers.arcgis.com/javascript/latest/api-reference/esri-views-BreakpointsOwner.html#widthBreakpoint) or [heightBreakpoint](https://developers.arcgis.com/javascript/latest/api-reference/esri-views-BreakpointsOwner.html#heightBreakpoint) will
   * be `medium`.
   *
   * @default 992
   */
  medium: number;
  /**
   * Sets the `small` breakpoint in pixels used by
   * [widthBreakpoint](https://developers.arcgis.com/javascript/latest/api-reference/esri-views-BreakpointsOwner.html#widthBreakpoint) and [heightBreakpoint](https://developers.arcgis.com/javascript/latest/api-reference/esri-views-BreakpointsOwner.html#heightBreakpoint). If the
   * view's [height](https://developers.arcgis.com/javascript/latest/api-reference/esri-views-View2D.html#height) or [width](https://developers.arcgis.com/javascript/latest/api-reference/esri-views-View2D.html#width) is between this value and the value
   * of the `xsmall` property, then the value of
   * [widthBreakpoint](https://developers.arcgis.com/javascript/latest/api-reference/esri-views-BreakpointsOwner.html#widthBreakpoint) or [heightBreakpoint](https://developers.arcgis.com/javascript/latest/api-reference/esri-views-BreakpointsOwner.html#heightBreakpoint) will
   * be `small`.
   *
   * @default 768
   */
  small: number;
  /**
   * Sets the `xsmall` breakpoint in pixels used by
   * [widthBreakpoint](https://developers.arcgis.com/javascript/latest/api-reference/esri-views-BreakpointsOwner.html#widthBreakpoint) and [heightBreakpoint](https://developers.arcgis.com/javascript/latest/api-reference/esri-views-BreakpointsOwner.html#heightBreakpoint). If the
   * view's [height](https://developers.arcgis.com/javascript/latest/api-reference/esri-views-View2D.html#height) or [width](https://developers.arcgis.com/javascript/latest/api-reference/esri-views-View2D.html#width) is smaller than this value, then the value of
   * [widthBreakpoint](https://developers.arcgis.com/javascript/latest/api-reference/esri-views-BreakpointsOwner.html#widthBreakpoint) or [heightBreakpoint](https://developers.arcgis.com/javascript/latest/api-reference/esri-views-BreakpointsOwner.html#heightBreakpoint) will
   * be `xsmall`.
   *
   * @default 544
   */
  xsmall: number;
}

export type BreakpointOrientation = "landscape" | "portrait";

export type BreakpointSize = "xsmall" | "small" | "medium" | "large" | "xlarge";

export interface AnalysisViewCreateEvent {
  /** The analysis for which the `analysisView` was created. */
  analysis: Analysis;
  /** The analysis view that was created. */
  analysisView: AnalysisViewUnion;
}

export interface AnalysisViewCreateErrorEvent {
  /** The analysis for which the `analysisView` was created. */
  analysis: Analysis;
  /** An error object describing why the analysis view could not be created. */
  error: Error;
}

export interface AnalysisViewDestroyEvent {
  /** The analysis whose analysis view was destroyed. */
  analysis: Analysis;
  /** The analysis view that was destroyed. */
  analysisView: AnalysisViewUnion;
}

export interface AnalysisViewEvents {
  /**
   * Fires when the view for an [Analysis](https://developers.arcgis.com/javascript/latest/api-reference/esri-analysis-Analysis.html) is created.
   *
   * @see [MapView#whenAnalysisView()](https://developers.arcgis.com/javascript/latest/api-reference/esri-views-MapView.html#whenAnalysisView)
   * @see [SceneView#whenAnalysisView()](https://developers.arcgis.com/javascript/latest/api-reference/esri-views-SceneView.html#whenAnalysisView)
   */
  "analysis-view-create": AnalysisViewCreateEvent;
  /**
   * Fires when an error occurs during the creation of an [Analysis](https://developers.arcgis.com/javascript/latest/api-reference/esri-analysis-Analysis.html) after an analysis
   * is added to the view.
   *
   * @see [MapView#whenAnalysisView()](https://developers.arcgis.com/javascript/latest/api-reference/esri-views-MapView.html#whenAnalysisView)
   * @see [SceneView#whenAnalysisView()](https://developers.arcgis.com/javascript/latest/api-reference/esri-views-SceneView.html#whenAnalysisView)
   */
  "analysis-view-create-error": AnalysisViewCreateErrorEvent;
  /** Fires after an [analysis view](https://developers.arcgis.com/javascript/latest/api-reference/esri-unionTypes.html#AnalysisViewUnion) is destroyed. */
  "analysis-view-destroy": AnalysisViewDestroyEvent;
}

export type SceneViewEventTypes = ViewEventTypes
  & AnalysisViewEvents;