import type FeatureLayer from "@arcgis/core/layers/FeatureLayer.js";
import type SubtypeGroupLayer from "@arcgis/core/layers/SubtypeGroupLayer.js";
import type SubtypeSublayer from "@arcgis/core/layers/support/SubtypeSublayer.js";
import type FeatureLayerView from "@arcgis/core/views/layers/FeatureLayerView.js";
import type { QueryObject } from "../interfaces.js";
import type { SupportedLayer } from "../../../interfaces.js";
import type { WebChart } from "../../../spec/web-chart.js";

/**
 * Indicates whether the input object is a feature collection.
 *
 * @param queryObject
 * @internal
 */
export function isFeatureCollectionLayer(queryObject: QueryObject): queryObject is FeatureLayerView;

/**
 * Indicates whether the input object is an instance of `FeatureLayerView`.
 *
 * @param queryObject
 * @internal
 */
export function isFeatureLayerView(queryObject: QueryObject | SubtypeGroupLayer): queryObject is FeatureLayerView;

/**
 * Indicates whether the input object is an instance of `FeatureLayer`.
 *
 * @param queryObject
 * @internal
 */
export function isFeatureLayer(queryObject: QueryObject): queryObject is FeatureLayer;

/**
 * Indicates whether the input object is an instance of `SubtypeGroupLayer`.
 *
 * @param queryObject
 * @internal
 */
export function isSubtypeGroupLayer(queryObject: QueryObject | SubtypeGroupLayer): queryObject is SubtypeGroupLayer;

/**
 * Indicates whether the input object is an instance of `SubtypeSublayer`.
 *
 * @param queryObject
 * @internal
 */
export function isSubtypeSublayer(queryObject: Pick<SubtypeSublayer, "type"> | QueryObject): queryObject is SubtypeSublayer;

/**
 * Indicates whether the input object is an instance of `SupportedLayer` (`FeatureLayer` or `SubtypeSublayer`).
 *
 * @param queryObject
 * @internal
 */
export function isSupportedLayer(queryObject: QueryObject): queryObject is SupportedLayer;

/**
 * Returns the main `Layer` instance associated with the layer being used.
 *
 * Only needed for the case where the layer is a `SubtypeSublayer`, in which case we use the parent layer which is a `SubtypeGroupLayer`.
 *
 * @param layer
 * @internal
 */
export function getMainLayer(layer: FeatureLayer | Pick<SubtypeSublayer, "parent" | "type">): FeatureLayer | SubtypeGroupLayer;

/**
 * @param layer
 * @internal
 */
export function getMainLayer(layer: FeatureLayer | Pick<SubtypeSublayer, "parent" | "type"> | undefined): FeatureLayer | SubtypeGroupLayer | null | undefined;

/**
 * @param layer
 * @internal
 */
export function getMainLayer(layer: FeatureLayer | Pick<SubtypeSublayer, "parent" | "type"> | undefined): FeatureLayer | SubtypeGroupLayer | null | undefined;

/**
 * Indicates whether a layer supports queries with a `distance` parameter
 *
 * @param layer - The layer to test
 * @returns A boolean
 * @internal
 */
export function doesLayerSupportQueryWithDistance(layer: SupportedLayer): boolean;

/**
 * Indicates whether a layer supports the queryBins operation for the heat chart use case.
 *
 * @param layer - The layer to test
 * @returns A boolean indicating whether the operation is supported
 * @internal
 */
export function doesLayerSupportsQueryBinsForHeatChart(layer: SupportedLayer): boolean;

/**
 * Indicates whether a layer supports the queryBins operation for the temporal data use case.
 * We currently only use the "date" operation.
 * If a split-by field is provided we verify whether `stackBy` parameter is supported (refer to `mapAttributeBinsQuery()`).
 *
 * @param layer - The layer to test
 * @param splitByField - The split-by field
 * @returns A boolean indicating whether the operation is supported
 * @internal
 */
export function doesLayerSupportsQueryBinsForTemporalData(layer?: FeatureLayerView | SubtypeGroupLayer | SupportedLayer, splitByField?: string): boolean;

/**
 * Indicates whether the layer supports the cacheHint parameter for the queryBins operation
 *
 * @param queryObject - The layer or feature layer view
 * @internal
 */
export function doesLayerSupportsCacheHintForQueryBins(queryObject: QueryObject): boolean;

/**
 * Indicates whether the layer supports the query bins operation for scatterplot:
 * - supports queryBins
 * - supports the type `fixedIntervalBin`
 * - statistics: supports MAX and COUNT
 *
 * @param queryObject - The layer or feature layer view
 * @internal
 */
export function doesLayerSupportsQueryBinsForScatterplot(queryObject: QueryObject): boolean;

/**
 * Returns a feature layer from a QueryObject instance.
 * It will use the QueryObject itself if it's a Feature Layer, or the `layer` property from it if it's a Feature Layer View.
 *
 * @param layerOrLayerView
 * @internal
 */
export function getLayerFromLayerOrLayerView(layerOrLayerView: FeatureLayerView | SupportedLayer): SupportedLayer;

/**
 * Returns a feature layer from a QueryObject instance.
 * It will use the QueryObject itself if it's a Feature Layer, or the `layer` property from it if it's a Feature Layer View.
 *
 * @param queryObject
 * @internal
 */
export function getLayerFromQueryObject(queryObject: QueryObject): SupportedLayer;

/**
 * Computes a feature layer capabilities regarding its spatial aggregation statistics.
 * Only considers the 'EnvelopeAggregate' for now.
 *
 * @param layer - The layer instance
 * @returns A sum up of the capabilities
 * @internal
 */
export function getLayerSpatialAggregationStatisticsCapabilities(layer: SupportedLayer): boolean;

/**
 * Adds a iLayer to a WebChart.
 * If the `queryObject` prop is provided an `iLayer` is added to the config.
 *
 * @param props - The chart config with no iLayer
 * @returns The update chart config with a `iLayer` property
 * @internal
 */
export function addILayer<T extends WebChart>(props: {
    chartConfig: T;
    queryObject?: FeatureLayerView | SupportedLayer;
}): T & WebChart;