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

export interface TablesMixinProperties {
  /**
   * A collection of [Layer](https://developers.arcgis.com/javascript/latest/references/core/layers/Layer/) instances that are tables
   * saved in a [Map](https://developers.arcgis.com/javascript/latest/references/core/Map/) and/or a [WebMap](https://developers.arcgis.com/javascript/latest/references/core/WebMap/).
   * In order for the table(s) to be recognized as such, the FeatureLayer's [FeatureLayer.isTable](https://developers.arcgis.com/javascript/latest/references/core/layers/FeatureLayer/#isTable)
   * property must return `true`. A table can be created via one of the options below:
   *
   * * Referencing the URL to a table in a feature service.
   * * Create a feature layer using the [Layer.fromArcGISServerUrl()](https://developers.arcgis.com/javascript/latest/references/core/layers/Layer/#fromArcGISServerUrl) method
   * and confirm that it is a table using feature layer's [FeatureLayer.isTable](https://developers.arcgis.com/javascript/latest/references/core/layers/FeatureLayer/#isTable) property.
   * This can be either a feature service or feature collection.
   * * Create  a feature layer using the [Layer.fromPortalItem()](https://developers.arcgis.com/javascript/latest/references/core/layers/Layer/#fromPortalItem) method
   * and confirm that it is a table using feature layer's [FeatureLayer.isTable](https://developers.arcgis.com/javascript/latest/references/core/layers/FeatureLayer/#isTable) property.
   * This can be either a feature service or feature collection.
   * * Create an in-memory, non-spatial, client-side feature layer.
   *
   * Beginning with 4.17, it is possible to persist non-spatial,
   * tables in a feature service to a WebMap, although in-memory
   * (feature collection) tables are not yet supported.
   *
   * Persisting tables within a [GroupLayer.tables](https://developers.arcgis.com/javascript/latest/references/core/layers/GroupLayer/#tables) is not yet supported. If this is needed,
   * add them to the [Map.tables](https://developers.arcgis.com/javascript/latest/references/core/Map/#tables) and/or [WebMap.tables](https://developers.arcgis.com/javascript/latest/references/core/WebMap/#tables).
   *
   * > [!CAUTION]
   * >
   * > Currently, only feature service [feature layers](https://developers.arcgis.com/javascript/latest/references/core/layers/FeatureLayer/) are recognized.
   * > To access spatial layers, use the `layers` property in either [Map.layers](https://developers.arcgis.com/javascript/latest/references/core/Map/#layers)
   * > or [WebMap.layers](https://developers.arcgis.com/javascript/latest/references/core/WebMap/#layers) classes
   *
   * @see [Sample - Creating a FeatureLayer - Add an array of client-side features](https://developers.arcgis.com/javascript/latest/references/core/layers/FeatureLayer/#creating-a-featurelayer)
   * @see [FeatureLayer.isTable](https://developers.arcgis.com/javascript/latest/references/core/layers/FeatureLayer/#isTable)
   * @see [Sample - Save a web map](https://developers.arcgis.com/javascript/latest/sample-code/webmap-save/)
   * @example
   * // This snippet shows how to add a table to a map's table collection.
   *
   * // FeatureLayer.isTable = false
   * const featureLayer = new FeatureLayer({
   *   url: "https://sampleserver6.arcgisonline.com/arcgis/rest/services/SF311/FeatureServer/0"
   * });
   * // Add featureLayer to the map
   * map.add(featureLayer);
   *
   * // FeatureLayer.isTable = true
   * const table = new FeatureLayer({
   *   url: "https://sampleserver6.arcgisonline.com/arcgis/rest/services/SF311/FeatureServer/1"
   * });
   *
   * // In order for the table to be stored within
   * // the map's table collection, load it and confirm it is the right type.
   *
   * table.load().then(() => {
   *   // Add the table to the collection
   *   map.tables.add(table);
   *   console.log("Table is added to map's table collection");
   * });
   * @example
   * // This snippet shows how to persist a table to an existing web map
   *
   * // FeatureLayer.isTable = true
   * const table = new FeatureLayer({
   *   url: "https://services.arcgis.com/V6ZHFr6zdgNZuVG0/arcgis/rest/services/Crash_details_table/FeatureServer/0"
   * });
   *
   * // Create Webmap instance
   * const webmap = new WebMap({
   *   portalItem: {
   *     id: webmapId
   *   }
   * });
   *
   * // When web map is ready, load the table and add it to the web map
   * webmap.when(() => {
   *   table.load().then(() => {
   *     console.log("Adding table");
   *     // Add table to the webmap's table collection
   *     webmap.tables.add(table);
   *   });
   * });
   *
   * // Call updateFrom on webmap and pass in the existing view
   * webmap.updateFrom(view).then(() => {
   *   // Call saveAs (or save) on the web map
   *   webmap.saveAs({
   *     // autocasts as new PortalItem()
   *     title: "New WebMap"
   *   });
   * });
   * @example
   * // This snippet shows how to add an in-memory table to a map
   *
   * // Create the array of objects containing field info
   * const fields = [{
   *   name: "ObjectID",
   *   alias: "ObjectID",
   *   type: "oid"
   * },
   * {
   *   name: "tree_type",
   *   alias: "Tree type",
   *   type: "string"
   * },
   * {
   *   name: "species",
   *   alias: "Species",
   *   type: "string"
   * }];
   *
   * // Create the array of graphics holding attribute info
   * const graphics = [{
   *   attributes: {
   *     "tree_type": "deciduous",
   *     "species": "maple",
   *     "ObjectID": 2
   *   }
   * }, {
   *   attributes: {
   *     "tree_type": "coniferous",
   *     "species": "pine",
   *     "ObjectID": 3
   *   }
   * }];
   *
   * // Create the feature layer (feature collection) table
   * const table = new FeatureLayer({
   *   fields: fields,
   *   objectIdField: "ObjectID",
   *   source: graphics
   * });
   *
   * // Check when map is ready and load the table
   * map.when(() => {
   *   table.load().then(() => {
   *     console.log("Adding table");
   *     map.tables.add(table);
   *   });
   * });
   */
  tables?: ReadonlyArrayOrCollection<Layer>;
}

/**
 * A mixin that provides properties to access tables.
 *
 * @since 4.17
 */
export abstract class TablesMixin {
  constructor(...args: any[]);
  /**
   * A collection of [Layer](https://developers.arcgis.com/javascript/latest/references/core/layers/Layer/) instances that are tables
   * saved in a [Map](https://developers.arcgis.com/javascript/latest/references/core/Map/) and/or a [WebMap](https://developers.arcgis.com/javascript/latest/references/core/WebMap/).
   * In order for the table(s) to be recognized as such, the FeatureLayer's [FeatureLayer.isTable](https://developers.arcgis.com/javascript/latest/references/core/layers/FeatureLayer/#isTable)
   * property must return `true`. A table can be created via one of the options below:
   *
   * * Referencing the URL to a table in a feature service.
   * * Create a feature layer using the [Layer.fromArcGISServerUrl()](https://developers.arcgis.com/javascript/latest/references/core/layers/Layer/#fromArcGISServerUrl) method
   * and confirm that it is a table using feature layer's [FeatureLayer.isTable](https://developers.arcgis.com/javascript/latest/references/core/layers/FeatureLayer/#isTable) property.
   * This can be either a feature service or feature collection.
   * * Create  a feature layer using the [Layer.fromPortalItem()](https://developers.arcgis.com/javascript/latest/references/core/layers/Layer/#fromPortalItem) method
   * and confirm that it is a table using feature layer's [FeatureLayer.isTable](https://developers.arcgis.com/javascript/latest/references/core/layers/FeatureLayer/#isTable) property.
   * This can be either a feature service or feature collection.
   * * Create an in-memory, non-spatial, client-side feature layer.
   *
   * Beginning with 4.17, it is possible to persist non-spatial,
   * tables in a feature service to a WebMap, although in-memory
   * (feature collection) tables are not yet supported.
   *
   * Persisting tables within a [GroupLayer.tables](https://developers.arcgis.com/javascript/latest/references/core/layers/GroupLayer/#tables) is not yet supported. If this is needed,
   * add them to the [Map.tables](https://developers.arcgis.com/javascript/latest/references/core/Map/#tables) and/or [WebMap.tables](https://developers.arcgis.com/javascript/latest/references/core/WebMap/#tables).
   *
   * > [!CAUTION]
   * >
   * > Currently, only feature service [feature layers](https://developers.arcgis.com/javascript/latest/references/core/layers/FeatureLayer/) are recognized.
   * > To access spatial layers, use the `layers` property in either [Map.layers](https://developers.arcgis.com/javascript/latest/references/core/Map/#layers)
   * > or [WebMap.layers](https://developers.arcgis.com/javascript/latest/references/core/WebMap/#layers) classes
   *
   * @see [Sample - Creating a FeatureLayer - Add an array of client-side features](https://developers.arcgis.com/javascript/latest/references/core/layers/FeatureLayer/#creating-a-featurelayer)
   * @see [FeatureLayer.isTable](https://developers.arcgis.com/javascript/latest/references/core/layers/FeatureLayer/#isTable)
   * @see [Sample - Save a web map](https://developers.arcgis.com/javascript/latest/sample-code/webmap-save/)
   * @example
   * // This snippet shows how to add a table to a map's table collection.
   *
   * // FeatureLayer.isTable = false
   * const featureLayer = new FeatureLayer({
   *   url: "https://sampleserver6.arcgisonline.com/arcgis/rest/services/SF311/FeatureServer/0"
   * });
   * // Add featureLayer to the map
   * map.add(featureLayer);
   *
   * // FeatureLayer.isTable = true
   * const table = new FeatureLayer({
   *   url: "https://sampleserver6.arcgisonline.com/arcgis/rest/services/SF311/FeatureServer/1"
   * });
   *
   * // In order for the table to be stored within
   * // the map's table collection, load it and confirm it is the right type.
   *
   * table.load().then(() => {
   *   // Add the table to the collection
   *   map.tables.add(table);
   *   console.log("Table is added to map's table collection");
   * });
   * @example
   * // This snippet shows how to persist a table to an existing web map
   *
   * // FeatureLayer.isTable = true
   * const table = new FeatureLayer({
   *   url: "https://services.arcgis.com/V6ZHFr6zdgNZuVG0/arcgis/rest/services/Crash_details_table/FeatureServer/0"
   * });
   *
   * // Create Webmap instance
   * const webmap = new WebMap({
   *   portalItem: {
   *     id: webmapId
   *   }
   * });
   *
   * // When web map is ready, load the table and add it to the web map
   * webmap.when(() => {
   *   table.load().then(() => {
   *     console.log("Adding table");
   *     // Add table to the webmap's table collection
   *     webmap.tables.add(table);
   *   });
   * });
   *
   * // Call updateFrom on webmap and pass in the existing view
   * webmap.updateFrom(view).then(() => {
   *   // Call saveAs (or save) on the web map
   *   webmap.saveAs({
   *     // autocasts as new PortalItem()
   *     title: "New WebMap"
   *   });
   * });
   * @example
   * // This snippet shows how to add an in-memory table to a map
   *
   * // Create the array of objects containing field info
   * const fields = [{
   *   name: "ObjectID",
   *   alias: "ObjectID",
   *   type: "oid"
   * },
   * {
   *   name: "tree_type",
   *   alias: "Tree type",
   *   type: "string"
   * },
   * {
   *   name: "species",
   *   alias: "Species",
   *   type: "string"
   * }];
   *
   * // Create the array of graphics holding attribute info
   * const graphics = [{
   *   attributes: {
   *     "tree_type": "deciduous",
   *     "species": "maple",
   *     "ObjectID": 2
   *   }
   * }, {
   *   attributes: {
   *     "tree_type": "coniferous",
   *     "species": "pine",
   *     "ObjectID": 3
   *   }
   * }];
   *
   * // Create the feature layer (feature collection) table
   * const table = new FeatureLayer({
   *   fields: fields,
   *   objectIdField: "ObjectID",
   *   source: graphics
   * });
   *
   * // Check when map is ready and load the table
   * map.when(() => {
   *   table.load().then(() => {
   *     console.log("Adding table");
   *     map.tables.add(table);
   *   });
   * });
   */
  get tables(): Collection<Layer>;
  set tables(value: ReadonlyArrayOrCollection<Layer>);
  /**
   * Returns a table based on the given table ID.
   *
   * @param tableId - The ID assigned to the table.
   * @returns Returns the requested table object.
   * @since 4.18
   */
  findTableById(tableId: string): Layer | null | undefined;
}