import type Layer from "./Layer.js";
import type LayerBase from "./Layer.js";
import type PortalItem from "../portal/PortalItem.js";
import type { ReadonlyCollection } from "../core/Collection.js";
import type { MultiOriginJSONSupportMixin } from "../core/MultiOriginJSONSupport.js";
import type { LayerSaveOptions, LayerSaveAsOptions } from "./types.js";
import type { BlendLayer, BlendLayerProperties } from "./mixins/BlendLayer.js";
import type { OperationalLayer, OperationalLayerProperties } from "./mixins/OperationalLayer.js";
import type { PortalLayer, PortalLayerProperties } from "./mixins/PortalLayer.js";
import type { ScaleRangeLayer, ScaleRangeLayerProperties } from "./mixins/ScaleRangeLayer.js";
import type { LayersMixin, LayersMixinProperties } from "../support/LayersMixin.js";
import type { TablesMixin, TablesMixinProperties } from "../support/TablesMixin.js";
import type { LayerProperties as LayerBaseProperties } from "./Layer.js";

export interface GroupLayerProperties extends LayerBaseProperties, LayersMixinProperties, TablesMixinProperties, PortalLayerProperties, OperationalLayerProperties, ScaleRangeLayerProperties, BlendLayerProperties, Partial<Pick<GroupLayer, "visibilityMode">> {
  /**
   * The maximum scale (most zoomed in) at which the layer is visible in the view.
   * If the map is zoomed in beyond this scale, the layer will not be visible.
   * A value of `0` means the layer does not have a maximum scale.
   * The maxScale value should always be smaller than the [minScale](https://developers.arcgis.com/javascript/latest/references/core/layers/GroupLayer/#minScale) value,
   * and greater than or equal to the service specification.
   *
   * @default 0
   * @since 4.19
   * @example
   * // The layer will not be visible when the view is zoomed in beyond a scale of 1:1,000
   * layer.maxScale = 1000;
   * @example
   * // The layer's visibility is not restricted to a maximum scale.
   * layer.maxScale = 0;
   * @example
   * // The layer will not be visible when the view is zoomed in beyond a scale of 1:1,000
   * layer.maxScale = 1000;
   * @example
   * // The layer's visibility is not restricted to a maximum scale.
   * layer.maxScale = 0;
   */
  maxScale?: number;
  /**
   * The minimum scale (most zoomed out) at which the layer is visible in the view.
   * If the map is zoomed out beyond this scale, the layer will not be visible.
   * A value of `0` means the layer does not have a minimum scale.
   * The minScale value should always be larger than the [maxScale](https://developers.arcgis.com/javascript/latest/references/core/layers/GroupLayer/#maxScale) value,
   * and lesser than or equal to the service specification.
   *
   * @default 0
   * @since 4.19
   * @example
   * // The layer will not be visible when the view is zoomed out beyond a scale of 1:3,000,000
   * layer.minScale = 3000000;
   * @example
   * // The layer's visibility is not restricted to a minimum scale.
   * layer.minScale = 0;
   * @example
   * // The layer will not be visible when the view is zoomed out beyond a scale of 1:3,000,000
   * layer.minScale = 3000000;
   * @example
   * // The layer's visibility is not restricted to a minimum scale.
   * layer.minScale = 0;
   */
  minScale?: number;
}

/**
 * GroupLayer provides the ability to organize several sublayers into one common layer. Suppose there are
 * several [FeatureLayers](https://developers.arcgis.com/javascript/latest/references/core/layers/FeatureLayer/) that all represent
 * water features in different dimensions. For example, wells (points), streams (lines), and lakes (polygons).
 * The GroupLayer provides the functionality to treat them as one layer called "Water Features" even though they
 * are stored as separate feature layers. To accomplish this, create a new GroupLayer and use the [add()](https://developers.arcgis.com/javascript/latest/references/core/layers/GroupLayer/#add)
 * method to add each of the water layers to the GroupLayer.
 *
 * The visibility of each layer is managed in the [listMode](https://developers.arcgis.com/javascript/latest/references/core/layers/GroupLayer/#listMode) and [visibilityMode](https://developers.arcgis.com/javascript/latest/references/core/layers/GroupLayer/#visibilityMode)
 * properties.
 *
 * @since 4.0
 * @see [Sample - GroupLayer with LayerList widget](https://developers.arcgis.com/javascript/latest/sample-code/widgets-layerlist-actions/)
 * @see [GroupLayerView](https://developers.arcgis.com/javascript/latest/references/core/views/layers/GroupLayerView/)
 * @see [FeatureLayer](https://developers.arcgis.com/javascript/latest/references/core/layers/FeatureLayer/)
 * @see [MapImageLayer](https://developers.arcgis.com/javascript/latest/references/core/layers/MapImageLayer/)
 * @see [TileLayer](https://developers.arcgis.com/javascript/latest/references/core/layers/TileLayer/)
 */
export default class GroupLayer extends GroupLayerSuperclass {
  constructor(properties?: GroupLayerProperties);
  /**
   * A flattened collection of all [layers](https://developers.arcgis.com/javascript/latest/references/core/layers/Layer/) in the group layer.
   * Nested group layers and their children layers are also part of this collection.
   * Layers should not be added directly to this collection. They must only be added via the
   * [layers](https://developers.arcgis.com/javascript/latest/references/core/layers/GroupLayer/#layers) property.
   *
   * > [!CAUTION]
   * >
   * > To access a flattened collection of tables, use the [allTables](https://developers.arcgis.com/javascript/latest/references/core/layers/GroupLayer/#allTables) property instead.
   *
   * @since 4.24
   * @example
   * // Find a layer with title "US Counties"
   * const foundLayer = groupLayer.allLayers.find((layer) => {
   *  return layer.title === "US Counties";
   * });
   *
   * // Listen for any layer being added or removed in the GroupLayer
   * groupLayer.allLayers.on("change", (event) => {
   *  console.log("Layer added: ", event.added);
   *  console.log("Layer removed: ", event.removed);
   *  console.log("Layer moved: ", event.moved);
   * });
   */
  get allLayers(): ReadonlyCollection<Layer>;
  /**
   * A flattened collection of tables anywhere in the group layer's hierarchy. This will contain
   * individual tables within [tables](https://developers.arcgis.com/javascript/latest/references/core/layers/GroupLayer/#tables), in addition to any children tables of
   * [nested group layers](https://developers.arcgis.com/javascript/latest/references/core/layers/GroupLayer/#layers). In order for the table(s) to be recognized as such, the
   * [feature layer's isTable](https://developers.arcgis.com/javascript/latest/references/core/layers/FeatureLayer/#isTable) property must return `true`.
   *
   * > [!CAUTION]
   * >
   * > Currently, only [feature layer](https://developers.arcgis.com/javascript/latest/references/core/layers/FeatureLayer/) tables are recognized.
   * > To access a flattened collection of spatial layers, use the [allLayers](https://developers.arcgis.com/javascript/latest/references/core/layers/GroupLayer/#allLayers) property instead.
   *
   * @since 4.24
   * @example
   * // A feature layer where isTable = true.
   * const foundTable = groupLayer.allTables.find((table) => {
   *   // Find a table with title "US Counties"
   *   return table.title === "US Counties";
   * });
   */
  get allTables(): ReadonlyCollection<Layer>;
  /**
   * The maximum scale (most zoomed in) at which the layer is visible in the view.
   * If the map is zoomed in beyond this scale, the layer will not be visible.
   * A value of `0` means the layer does not have a maximum scale.
   * The maxScale value should always be smaller than the [minScale](https://developers.arcgis.com/javascript/latest/references/core/layers/GroupLayer/#minScale) value,
   * and greater than or equal to the service specification.
   *
   * @default 0
   * @since 4.19
   * @example
   * // The layer will not be visible when the view is zoomed in beyond a scale of 1:1,000
   * layer.maxScale = 1000;
   * @example
   * // The layer's visibility is not restricted to a maximum scale.
   * layer.maxScale = 0;
   * @example
   * // The layer will not be visible when the view is zoomed in beyond a scale of 1:1,000
   * layer.maxScale = 1000;
   * @example
   * // The layer's visibility is not restricted to a maximum scale.
   * layer.maxScale = 0;
   */
  accessor maxScale: number;
  /**
   * The minimum scale (most zoomed out) at which the layer is visible in the view.
   * If the map is zoomed out beyond this scale, the layer will not be visible.
   * A value of `0` means the layer does not have a minimum scale.
   * The minScale value should always be larger than the [maxScale](https://developers.arcgis.com/javascript/latest/references/core/layers/GroupLayer/#maxScale) value,
   * and lesser than or equal to the service specification.
   *
   * @default 0
   * @since 4.19
   * @example
   * // The layer will not be visible when the view is zoomed out beyond a scale of 1:3,000,000
   * layer.minScale = 3000000;
   * @example
   * // The layer's visibility is not restricted to a minimum scale.
   * layer.minScale = 0;
   * @example
   * // The layer will not be visible when the view is zoomed out beyond a scale of 1:3,000,000
   * layer.minScale = 3000000;
   * @example
   * // The layer's visibility is not restricted to a minimum scale.
   * layer.minScale = 0;
   */
  accessor minScale: number;
  /** The layer type provides a convenient way to check the type of the layer without the need to import specific layer modules. */
  get type(): "group";
  /**
   * Indicates how to manage the visibility of the children layers. Possible values
   * are described in the table below.
   *
   * Value | Description
   * ------|------------
   * independent | Each child layer manages its visibility independent from other layers.
   * inherited | Each child layer's visibility matches the [GroupLayer's visibility](https://developers.arcgis.com/javascript/latest/references/core/layers/GroupLayer/#visible).
   * exclusive | Only one child layer is visible at a time.
   */
  accessor visibilityMode: GroupLayerVisibilityMode;
  /**
   * Loads all the externally loadable resources associated with the group layer.
   * For the group layer this will load all the layers.
   *
   * @returns Resolves when all the loadable resources have been loaded.
   *   Rejects if at least one of the loadable resources failed to load.
   * @since 4.9
   * @see [load()](https://developers.arcgis.com/javascript/latest/references/core/layers/GroupLayer/#load)
   * @example
   * // Load all resources but ignore if one or more of them failed to load
   * groupLayer.loadAll()
   *   .catch((error) => {
   *     // Ignore any failed resources
   *   })
   *   .then(() => {
   *     console.log("All loaded");
   *   });
   */
  loadAll(): Promise<this>;
  /**
   * Saves the layer to its existing portal item in the [Portal](https://developers.arcgis.com/javascript/latest/references/core/portal/Portal/)
   * authenticated within the user's current session. If the layer is not saved to a
   * [PortalItem](https://developers.arcgis.com/javascript/latest/references/core/portal/PortalItem/), then you should use [saveAs()](https://developers.arcgis.com/javascript/latest/references/core/layers/GroupLayer/#saveAs).
   *
   * > [!WARNING]
   * >
   * > **Known Limitations**
   * >
   * > Only layers supported by the [web map specification](https://developers.arcgis.com/web-map-specification/) can be saved to a group layer.
   * > [Media layers](https://developers.arcgis.com/javascript/latest/references/core/layers/MediaLayer/) can only have a single [ImageElement](https://developers.arcgis.com/javascript/latest/references/core/layers/support/ImageElement/)
   * > as the [MediaLayer.source](https://developers.arcgis.com/javascript/latest/references/core/layers/MediaLayer/#source).
   *
   * @param options - Various options for saving the layer.
   * @returns When resolved, returns the portal item to which the layer is saved.
   * @since 4.28
   * @example const portalItem = await layer.save();
   */
  save(options?: LayerSaveOptions): Promise<PortalItem>;
  /**
   * Saves the layer to a new portal item in the [Portal](https://developers.arcgis.com/javascript/latest/references/core/portal/Portal/) authenticated within the user's current session.
   *
   * > [!WARNING]
   * >
   * > **Known Limitations**
   * >
   * > Only layers supported by the [web map specification](https://developers.arcgis.com/web-map-specification/) can be saved to a group layer.
   * > [Media layers](https://developers.arcgis.com/javascript/latest/references/core/layers/MediaLayer/) can only have a single [ImageElement](https://developers.arcgis.com/javascript/latest/references/core/layers/support/ImageElement/)
   * > as the [MediaLayer.source](https://developers.arcgis.com/javascript/latest/references/core/layers/MediaLayer/#source).
   *
   * @param portalItem - The portal item to which the layer will be saved.
   * @param options - Various options for saving the layer.
   * @returns When resolved, returns the portal item to which the layer is saved.
   * @since 4.28
   * @example
   * const portalItem = new PortalItem();
   * await layer.saveAs(portalItem);
   */
  saveAs(portalItem: PortalItem, options?: LayerSaveAsOptions): Promise<PortalItem>;
}
declare const GroupLayerSuperclass: typeof LayerBase & typeof MultiOriginJSONSupportMixin & typeof LayersMixin & typeof TablesMixin & typeof PortalLayer & typeof OperationalLayer & typeof ScaleRangeLayer & typeof BlendLayer

export type GroupLayerVisibilityMode = "independent" | "exclusive" | "inherited";