import type Field from "../../layers/support/Field.js";
import type JoinTableDataSource from "./JoinTableDataSource.js";
import type QueryTableDataSource from "./QueryTableDataSource.js";
import type RasterDataSource from "./RasterDataSource.js";
import type TableDataSource from "./TableDataSource.js";
import type { JSONSupport, JSONSupportMixinProperties } from "../../core/JSONSupport.js";
import type { FieldProperties } from "../../layers/support/Field.js";
import type { TableDataSourceProperties } from "./TableDataSource.js";
import type { RasterDataSourceProperties } from "./RasterDataSource.js";
import type { QueryTableDataSourceProperties } from "./QueryTableDataSource.js";
import type { JoinTableDataSourceProperties } from "./JoinTableDataSource.js";

export interface DynamicDataLayerProperties extends JSONSupportMixinProperties {
  /**
   * A table,
   * feature class, or raster that resides in a registered workspace (either a folder or geodatabase).
   * The data sources are not visible in the Services Directory by default. They may be viewed, published, and configured using
   * the ArcGIS Server Manager.
   */
  dataSource?: (JoinTableDataSourceProperties & { type: "join-table" }) | (QueryTableDataSourceProperties & { type: "query-table" }) | (RasterDataSourceProperties & { type: "raster" }) | (TableDataSourceProperties & { type: "table" });
  /**
   * Controls field visibility in the layer. Only specified fields will be visible.
   * If `null`, all fields are visible in the dynamic layer. The specification for a field object is
   * provided below.
   */
  fields?: FieldProperties[];
}

/**
 * A dynamic data layer is a layer created on-the-fly with data stored in a
 * [registered workspace](https://enterprise.arcgis.com/en/server/latest/manage-data/windows/overview-register-data-with-arcgis-server.htm). This is data that can be rendered and queried on the fly,
 * but that isn't explicitly exposed as a service sublayer.
 * Depending on the type of data source, these layers are classified as
 * one of the following:
 *
 * Data source | Description
 * ------------|------------
 * [TableDataSource](https://developers.arcgis.com/javascript/latest/api-reference/esri-rest-layerSources-TableDataSource.html) | A feature class with geometries or table without geometries. When a table data source does not contain geometries, it may be used as one of the sources in a {@link rest/layerSources/DataLayerSource!JoinTableDataSource join operation}. Feature class tables may be used on their own since they contain a geometry field.
 * [QueryTableDataSource](https://developers.arcgis.com/javascript/latest/api-reference/esri-rest-layerSources-QueryTableDataSource.html) | A feature class or table that may be queried on the fly with a SQL where clause. This data source is useful for scenarios where you have a table containing unique geometries and another table with multiple records that match to each geometry. You can use the QueryTableDataSource to select only a subset of those matching records (so records in both tables have a one-to-one relationship with each other) and join them to the table with geometries.
 * [RasterDataSource](https://developers.arcgis.com/javascript/latest/api-reference/esri-rest-layerSources-RasterDataSource.html) | A raster dataset used for visualization purposes only.
 * {@link rest/layerSources/DataLayerSource!JoinTableDataSource} | This data source consists of two data sources joined by a common attribute or key. The left table data source typically contains geometries, while the right source may be a table or query table without geometries.
 *
 * @see [Sample - MapImageLayer: toggle sublayer visibility](https://developers.arcgis.com/javascript/latest/sample-code/layers-mapimagelayer-sublayers/)
 * @see [Sample - MapImageLayer: dynamic data layer with table join](https://developers.arcgis.com/javascript/latest/sample-code/layers-dynamicdatalayer-table-join/)
 * @see [Sample - MapImageLayer: dynamic data layer with query table](https://developers.arcgis.com/javascript/latest/sample-code/layers-dynamicdatalayer-query-table/)
 * @see [Sample - MapImageLayer: raster data source](https://developers.arcgis.com/javascript/latest/sample-code/layers-dynamicdatalayer-raster/)
 * @see [ArcGIS REST API - Dynamic data layer](https://developers.arcgis.com/rest/services-reference/enterprise/layer-source-object/#dynamic-data-layer)
 * @example
 * let layer = new MapImageLayer({
 *   url: "https://sampleserver6.arcgisonline.com/arcgis/rest/services/Census/MapServer",
 *   sublayers: [{
 *     id: 0,
 *     renderer: renderer,
 *       opacity: 0.9,
 *       source: {
 *         type: "data-layer",
 *         dataSource: {
 *           type: "join-table",
 *           leftTableSource: {
 *             type: "map-layer",
 *             mapLayerId: 3
 *           },
 *           rightTableSource: {
 *             type: "data-layer",
 *             // references a table in a registered workspace that doesn't have geometries
 *             dataSource: {
 *               type: "table",
 *               workspaceId: "CensusFileGDBWorkspaceID",
 *               dataSourceName: "ancestry"
 *             }
 *           },
 *           leftTableKey: "STATE_NAME",
 *           rightTableKey: "State",
 *           joinType: "left-outer-join"
 *         }
 *       }
 *     }
 *   ]
 * });
 */
export default abstract class DynamicDataLayer extends JSONSupport {
  /**
   * A table,
   * feature class, or raster that resides in a registered workspace (either a folder or geodatabase).
   * The data sources are not visible in the Services Directory by default. They may be viewed, published, and configured using
   * the ArcGIS Server Manager.
   */
  get dataSource(): JoinTableDataSource | QueryTableDataSource | RasterDataSource | TableDataSource;
  set dataSource(value: (JoinTableDataSourceProperties & { type: "join-table" }) | (QueryTableDataSourceProperties & { type: "query-table" }) | (RasterDataSourceProperties & { type: "raster" }) | (TableDataSourceProperties & { type: "table" }));
  /**
   * Controls field visibility in the layer. Only specified fields will be visible.
   * If `null`, all fields are visible in the dynamic layer. The specification for a field object is
   * provided below.
   */
  get fields(): Field[];
  set fields(value: FieldProperties[]);
  /**
   * This value is always `data-layer` and is inferred when
   * the `dataSource` property is set.
   */
  get type(): "data-layer";
}