import type Layer from "../layers/Layer.js";
import type Collection from "../core/Collection.js";
import type { ReadonlyArrayOrCollection } from "../core/Collection.js";

export interface LayersMixinProperties {
  /**
   * A collection of operational [layers](https://developers.arcgis.com/javascript/latest/references/core/layers/Layer/). This property
   * contains the operational layers, such as [FeatureLayers](https://developers.arcgis.com/javascript/latest/references/core/layers/FeatureLayer/),
   * [WebTileLayers](https://developers.arcgis.com/javascript/latest/references/core/layers/WebTileLayer/) and [GraphicsLayers](https://developers.arcgis.com/javascript/latest/references/core/layers/GraphicsLayer/)  that may be queried, assigned different renderers, analyzed, etc. It does not include
   * [basemaps](https://developers.arcgis.com/javascript/latest/references/core/Basemap/).
   *
   * A [Layer](https://developers.arcgis.com/javascript/latest/references/core/layers/Layer/) is a collection of one or more features, or [graphics](https://developers.arcgis.com/javascript/latest/references/core/Graphic/), that represent real-world phenomena. Each feature contains a [Symbol](https://developers.arcgis.com/javascript/latest/references/core/symbols/Symbol/)  and [geographic data](https://developers.arcgis.com/javascript/latest/references/core/geometry/Geometry/) that allows it to be rendered on the map as a
   * graphic with spatial context. Features within the layer may also contain data attributes that provide
   * additional information that may be viewed in [popup windows](https://developers.arcgis.com/javascript/latest/references/core/widgets/Popup/) and used for [rendering the layer](https://developers.arcgis.com/javascript/latest/references/core/renderers/Renderer/).
   *
   * Layers may be added in the [constructor](https://developers.arcgis.com/javascript/latest/references/core/support/LayersMixin/#LayersMixinProperties), with the [add()](https://developers.arcgis.com/javascript/latest/references/core/support/LayersMixin/#add) or [addMany()](https://developers.arcgis.com/javascript/latest/references/core/support/LayersMixin/#addMany) methods,
   * or directly to the layers
   * collection using [Collection.add()](https://developers.arcgis.com/javascript/latest/references/core/core/Collection/#add) or [Collection.addMany()](https://developers.arcgis.com/javascript/latest/references/core/core/Collection/#addMany).
   *
   * In 3D, for layers that are rendered on the terrain, the order of the layers also depends on the
   * type of layer. Tiled layers ([BaseTileLayer](https://developers.arcgis.com/javascript/latest/references/core/layers/BaseTileLayer/), [ImageryTileLayer](https://developers.arcgis.com/javascript/latest/references/core/layers/ImageryTileLayer/),
   * [OpenStreetMapLayer](https://developers.arcgis.com/javascript/latest/references/core/layers/OpenStreetMapLayer/), [TileLayer](https://developers.arcgis.com/javascript/latest/references/core/layers/TileLayer/), [VectorTileLayer](https://developers.arcgis.com/javascript/latest/references/core/layers/VectorTileLayer/), [WCSLayer](https://developers.arcgis.com/javascript/latest/references/core/layers/WCSLayer/),
   * [WebTileLayer](https://developers.arcgis.com/javascript/latest/references/core/layers/WebTileLayer/) and [WMTSLayer](https://developers.arcgis.com/javascript/latest/references/core/layers/WMTSLayer/)) are always drawn first in the same order as specified in the layer collection.
   * Dynamic layers ([MapImageLayer](https://developers.arcgis.com/javascript/latest/references/core/layers/MapImageLayer/), [ImageryLayer](https://developers.arcgis.com/javascript/latest/references/core/layers/ImageryLayer/), [WMSLayer](https://developers.arcgis.com/javascript/latest/references/core/layers/WMSLayer/), and
   * feature based layers with [elevation mode](https://developers.arcgis.com/javascript/latest/references/core/layers/FeatureLayer/#elevationInfo) `on-the-ground`) are rendered
   * on top using the order from the layer collection.
   *
   * > [!WARNING]
   * >
   * > A [Layer](https://developers.arcgis.com/javascript/latest/references/core/layers/Layer/) may only be added to one parent. Adding the
   * > same layer to multiple [Maps](https://developers.arcgis.com/javascript/latest/references/core/Map/) or
   * > [GroupLayers](https://developers.arcgis.com/javascript/latest/references/core/layers/GroupLayer/) is not possible.
   * > If you attempt to do so, the layer will automatically be removed
   * > from its current parent and placed in the new parent.
   * >
   * > ```js
   * > let layer = new GraphicsLayer();
   * > // The layer belongs to map1
   * > map1.layers.add(layer);
   * > // The layer now belongs to map2
   * > // and implicitly does: map1.layers.remove(layer)
   * > map2.layers.add(layer);
   * > ```
   *
   * > [!WARNING]
   * >
   * > To access tables from [feature layers](https://developers.arcgis.com/javascript/latest/references/core/layers/FeatureLayer/), use
   * > the `tables` property in either [Map.tables](https://developers.arcgis.com/javascript/latest/references/core/Map/#tables) or [WebMap.tables](https://developers.arcgis.com/javascript/latest/references/core/WebMap/#tables) classes.
   *
   * @example
   * // Add layers in the constructor of Map using an array
   * let fl = new FeatureLayer(url);
   * let gl = new GraphicsLayer();
   * let map = new Map({
   *   layers: [fl, gl]
   * });
   *
   * // Add layers using add()
   * map.addMany([fl, gl]);
   *
   * // Add layers using layers collection
   * map.layers.addMany([fl, gl]);
   *
   * // Add layers using layers collection's push method
   * map.layers.push(fl, gl);
   */
  layers?: ReadonlyArrayOrCollection<Layer>;
}

/**
 * Mixin for [Map](https://developers.arcgis.com/javascript/latest/references/core/Map/).
 *
 * @since 4.0
 */
export abstract class LayersMixin {
  constructor(...args: any[]);
  /**
   * A collection of operational [layers](https://developers.arcgis.com/javascript/latest/references/core/layers/Layer/). This property
   * contains the operational layers, such as [FeatureLayers](https://developers.arcgis.com/javascript/latest/references/core/layers/FeatureLayer/),
   * [WebTileLayers](https://developers.arcgis.com/javascript/latest/references/core/layers/WebTileLayer/) and [GraphicsLayers](https://developers.arcgis.com/javascript/latest/references/core/layers/GraphicsLayer/)  that may be queried, assigned different renderers, analyzed, etc. It does not include
   * [basemaps](https://developers.arcgis.com/javascript/latest/references/core/Basemap/).
   *
   * A [Layer](https://developers.arcgis.com/javascript/latest/references/core/layers/Layer/) is a collection of one or more features, or [graphics](https://developers.arcgis.com/javascript/latest/references/core/Graphic/), that represent real-world phenomena. Each feature contains a [Symbol](https://developers.arcgis.com/javascript/latest/references/core/symbols/Symbol/)  and [geographic data](https://developers.arcgis.com/javascript/latest/references/core/geometry/Geometry/) that allows it to be rendered on the map as a
   * graphic with spatial context. Features within the layer may also contain data attributes that provide
   * additional information that may be viewed in [popup windows](https://developers.arcgis.com/javascript/latest/references/core/widgets/Popup/) and used for [rendering the layer](https://developers.arcgis.com/javascript/latest/references/core/renderers/Renderer/).
   *
   * Layers may be added in the [constructor](https://developers.arcgis.com/javascript/latest/references/core/support/LayersMixin/#LayersMixinProperties), with the [add()](https://developers.arcgis.com/javascript/latest/references/core/support/LayersMixin/#add) or [addMany()](https://developers.arcgis.com/javascript/latest/references/core/support/LayersMixin/#addMany) methods,
   * or directly to the layers
   * collection using [Collection.add()](https://developers.arcgis.com/javascript/latest/references/core/core/Collection/#add) or [Collection.addMany()](https://developers.arcgis.com/javascript/latest/references/core/core/Collection/#addMany).
   *
   * In 3D, for layers that are rendered on the terrain, the order of the layers also depends on the
   * type of layer. Tiled layers ([BaseTileLayer](https://developers.arcgis.com/javascript/latest/references/core/layers/BaseTileLayer/), [ImageryTileLayer](https://developers.arcgis.com/javascript/latest/references/core/layers/ImageryTileLayer/),
   * [OpenStreetMapLayer](https://developers.arcgis.com/javascript/latest/references/core/layers/OpenStreetMapLayer/), [TileLayer](https://developers.arcgis.com/javascript/latest/references/core/layers/TileLayer/), [VectorTileLayer](https://developers.arcgis.com/javascript/latest/references/core/layers/VectorTileLayer/), [WCSLayer](https://developers.arcgis.com/javascript/latest/references/core/layers/WCSLayer/),
   * [WebTileLayer](https://developers.arcgis.com/javascript/latest/references/core/layers/WebTileLayer/) and [WMTSLayer](https://developers.arcgis.com/javascript/latest/references/core/layers/WMTSLayer/)) are always drawn first in the same order as specified in the layer collection.
   * Dynamic layers ([MapImageLayer](https://developers.arcgis.com/javascript/latest/references/core/layers/MapImageLayer/), [ImageryLayer](https://developers.arcgis.com/javascript/latest/references/core/layers/ImageryLayer/), [WMSLayer](https://developers.arcgis.com/javascript/latest/references/core/layers/WMSLayer/), and
   * feature based layers with [elevation mode](https://developers.arcgis.com/javascript/latest/references/core/layers/FeatureLayer/#elevationInfo) `on-the-ground`) are rendered
   * on top using the order from the layer collection.
   *
   * > [!WARNING]
   * >
   * > A [Layer](https://developers.arcgis.com/javascript/latest/references/core/layers/Layer/) may only be added to one parent. Adding the
   * > same layer to multiple [Maps](https://developers.arcgis.com/javascript/latest/references/core/Map/) or
   * > [GroupLayers](https://developers.arcgis.com/javascript/latest/references/core/layers/GroupLayer/) is not possible.
   * > If you attempt to do so, the layer will automatically be removed
   * > from its current parent and placed in the new parent.
   * >
   * > ```js
   * > let layer = new GraphicsLayer();
   * > // The layer belongs to map1
   * > map1.layers.add(layer);
   * > // The layer now belongs to map2
   * > // and implicitly does: map1.layers.remove(layer)
   * > map2.layers.add(layer);
   * > ```
   *
   * > [!WARNING]
   * >
   * > To access tables from [feature layers](https://developers.arcgis.com/javascript/latest/references/core/layers/FeatureLayer/), use
   * > the `tables` property in either [Map.tables](https://developers.arcgis.com/javascript/latest/references/core/Map/#tables) or [WebMap.tables](https://developers.arcgis.com/javascript/latest/references/core/WebMap/#tables) classes.
   *
   * @example
   * // Add layers in the constructor of Map using an array
   * let fl = new FeatureLayer(url);
   * let gl = new GraphicsLayer();
   * let map = new Map({
   *   layers: [fl, gl]
   * });
   *
   * // Add layers using add()
   * map.addMany([fl, gl]);
   *
   * // Add layers using layers collection
   * map.layers.addMany([fl, gl]);
   *
   * // Add layers using layers collection's push method
   * map.layers.push(fl, gl);
   */
  get layers(): Collection<Layer>;
  set layers(value: ReadonlyArrayOrCollection<Layer>);
  /**
   * Adds a layer to the [layers collection](https://developers.arcgis.com/javascript/latest/references/core/support/LayersMixin/#layers). The [Collection.@before-changes](https://developers.arcgis.com/javascript/latest/references/core/core/Collection/#event-before-changes),
   * [Collection.@before-add](https://developers.arcgis.com/javascript/latest/references/core/core/Collection/#event-before-add), [Collection.@after-add](https://developers.arcgis.com/javascript/latest/references/core/core/Collection/#event-after-add),
   * [Collection.@after-changes](https://developers.arcgis.com/javascript/latest/references/core/core/Collection/#event-after-changes) and [Collection.@change](https://developers.arcgis.com/javascript/latest/references/core/core/Collection/#event-change)
   * events will be emitted when this method is called.
   *
   * @param layer - Layer or a promise that resolves to a layer to add to the [layers collection](https://developers.arcgis.com/javascript/latest/references/core/support/LayersMixin/#layers).
   * @param index - A layer can be added at a specified index in the [layers collection](https://developers.arcgis.com/javascript/latest/references/core/support/LayersMixin/#layers).
   *                         If no index is specified or the index specified is greater
   *                         than the current number of layers, the layer is automatically
   *                         appended to the list of layers in the [layers collection](https://developers.arcgis.com/javascript/latest/references/core/support/LayersMixin/#layers) and the index is
   *                         normalized.
   * @see [layer collection's push() method](https://developers.arcgis.com/javascript/latest/references/core/core/Collection/#push)
   * @example
   * // add() and push methods can be used
   * // to add a layer to layers collection
   *
   * // add a layer to layers collection using add
   * map.add(layer);
   *
   * // add a layer at the end of layers collection
   * map.layers.push(layer);
   */
  add(layer: Layer | PromiseLike<Layer>, index?: number): void;
  /**
   * Adds a layer or an array of layers to the [layers collection](https://developers.arcgis.com/javascript/latest/references/core/support/LayersMixin/#layers). The [Collection.@before-changes](https://developers.arcgis.com/javascript/latest/references/core/core/Collection/#event-before-changes),
   * [Collection.@before-add](https://developers.arcgis.com/javascript/latest/references/core/core/Collection/#event-before-add), [Collection.@after-add](https://developers.arcgis.com/javascript/latest/references/core/core/Collection/#event-after-add),
   * [Collection.@after-changes](https://developers.arcgis.com/javascript/latest/references/core/core/Collection/#event-after-changes) and [Collection.@change](https://developers.arcgis.com/javascript/latest/references/core/core/Collection/#event-change)
   * events will be emitted when this method is called.
   *
   * The [Collection.push()](https://developers.arcgis.com/javascript/latest/references/core/core/Collection/#push) method on the layers collection also can be used to add a layer or layers.
   *
   * @param layers - Layer(s) to be added to the [layers collection](https://developers.arcgis.com/javascript/latest/references/core/support/LayersMixin/#layers).
   * @param index - A layer can be added at a specified index in the [layers collection](https://developers.arcgis.com/javascript/latest/references/core/support/LayersMixin/#layers).
   *                         If no index is specified or the index specified is greater
   *                         than the current number of layers, the layer is automatically
   *                         appended to the list of layers in the [layers collection](https://developers.arcgis.com/javascript/latest/references/core/support/LayersMixin/#layers) and the index is
   *                         normalized.
   * @see [layer collection's push() method](https://developers.arcgis.com/javascript/latest/references/core/core/Collection/#push)
   * @example
   * // addMany and push methods can be used
   * // to add layers to layers collection
   *
   * // add an array of layers to layers collection using addMany
   * map.addMany([layer, layer2]);
   *
   * // add layers to layers collection using push method
   * map.layers.push(layer, layer2);
   */
  addMany(layers: Layer[], index?: number): void;
  /**
   * Returns a layer based on the given layer ID.
   *
   * @param layerId - The ID assigned to the layer.
   * @returns Returns the requested layer object.
   */
  findLayerById(layerId: string): Layer | null | undefined;
  /**
   * Removes the specified layer from the layers collection. The [Collection.@before-changes](https://developers.arcgis.com/javascript/latest/references/core/core/Collection/#event-before-changes),
   * [Collection.@before-remove](https://developers.arcgis.com/javascript/latest/references/core/core/Collection/#event-before-remove), [Collection.@after-remove](https://developers.arcgis.com/javascript/latest/references/core/core/Collection/#event-after-remove),
   * [Collection.@after-changes](https://developers.arcgis.com/javascript/latest/references/core/core/Collection/#event-after-changes) and [Collection.@change](https://developers.arcgis.com/javascript/latest/references/core/core/Collection/#event-change)
   * events will be emitted when this method is called.
   *
   * @param layer - Layer to remove from the layers collection.
   * @returns Returns the layer removed from the layers collection.
   */
  remove(layer: Layer): Layer | null | undefined;
  /**
   * Removes all layers. The [Collection.@before-changes](https://developers.arcgis.com/javascript/latest/references/core/core/Collection/#event-before-changes),
   * [Collection.@before-remove](https://developers.arcgis.com/javascript/latest/references/core/core/Collection/#event-before-remove), [Collection.@after-remove](https://developers.arcgis.com/javascript/latest/references/core/core/Collection/#event-after-remove),
   * [Collection.@after-changes](https://developers.arcgis.com/javascript/latest/references/core/core/Collection/#event-after-changes) and [Collection.@change](https://developers.arcgis.com/javascript/latest/references/core/core/Collection/#event-change)
   * events will be emitted when this method is called.
   *
   * @returns Returns the layers removed from the layers collection.
   */
  removeAll(): Layer[];
  /**
   * Removes the specified layers. The [Collection.@before-changes](https://developers.arcgis.com/javascript/latest/references/core/core/Collection/#event-before-changes),
   * [Collection.@before-remove](https://developers.arcgis.com/javascript/latest/references/core/core/Collection/#event-before-remove), [Collection.@after-remove](https://developers.arcgis.com/javascript/latest/references/core/core/Collection/#event-after-remove),
   * [Collection.@after-changes](https://developers.arcgis.com/javascript/latest/references/core/core/Collection/#event-after-changes) and [Collection.@change](https://developers.arcgis.com/javascript/latest/references/core/core/Collection/#event-change)
   * events will be emitted when this method is called.
   *
   * @param layers - Array of layers to remove from the layers collection.
   * @returns Returns the layers removed from the layers collection.
   */
  removeMany(layers: Layer[]): Layer[];
  /**
   * Changes the layer order. The first layer added is always the base layer,
   * even if its order is changed. The [Collection.@change](https://developers.arcgis.com/javascript/latest/references/core/core/Collection/#event-change)
   * event will be emitted when this method is called.
   *
   * In 3D, for layers that are rendered on the terrain, the order of the layers also depends on the
   * type of layer. Tiled layers ([BaseTileLayer](https://developers.arcgis.com/javascript/latest/references/core/layers/BaseTileLayer/), [ImageryTileLayer](https://developers.arcgis.com/javascript/latest/references/core/layers/ImageryTileLayer/),
   * [OpenStreetMapLayer](https://developers.arcgis.com/javascript/latest/references/core/layers/OpenStreetMapLayer/), [TileLayer](https://developers.arcgis.com/javascript/latest/references/core/layers/TileLayer/), [VectorTileLayer](https://developers.arcgis.com/javascript/latest/references/core/layers/VectorTileLayer/), [WCSLayer](https://developers.arcgis.com/javascript/latest/references/core/layers/WCSLayer/),
   * [WebTileLayer](https://developers.arcgis.com/javascript/latest/references/core/layers/WebTileLayer/) and [WMTSLayer](https://developers.arcgis.com/javascript/latest/references/core/layers/WMTSLayer/)) are always drawn first in the same order as specified in the layer collection.
   * Dynamic layers ([MapImageLayer](https://developers.arcgis.com/javascript/latest/references/core/layers/MapImageLayer/), [ImageryLayer](https://developers.arcgis.com/javascript/latest/references/core/layers/ImageryLayer/), [WMSLayer](https://developers.arcgis.com/javascript/latest/references/core/layers/WMSLayer/), and
   * feature based layers with [elevation mode](https://developers.arcgis.com/javascript/latest/references/core/layers/FeatureLayer/#elevationInfo) `on-the-ground`) are rendered
   * on top using the order from the layer collection.
   *
   * @param layer - The layer to be moved.
   * @param index - The index location for placing the layer. The bottom-most
   *                         layer has an index of `0`.
   * @returns Returns the layer that was moved.
   */
  reorder(layer: Layer, index?: number): Layer | null | undefined;
}