import type Geometry from "@arcgis/core/geometry/Geometry.js";
import type FeatureLayer from "@arcgis/core/layers/FeatureLayer.js";
import type SubtypeSublayer from "@arcgis/core/layers/support/SubtypeSublayer.js";
import type AttributeBinsQuery from "@arcgis/core/rest/support/AttributeBinsQuery.js";
import type Query from "@arcgis/core/rest/support/Query.js";
import type TimeExtent from "@arcgis/core/time/TimeExtent.js";
import type { QueryProperties } from "@arcgis/core/rest/support/Query.js";
import type { RESTFieldType } from "../../../spec/rest-js-object-literals.js";
import type { WebChartHeatChartSeries, WebChartQuery, WebChartTemporalBinning } from "../../../spec/web-chart.js";
import type { QueryObject } from "../interfaces.js";
import type { ChartOptions } from "../../../chart-rendering/common/interfaces.js";

/**
 * Indicates whether a query can be cached. It is not when:
 * - a geometry is set (unless it's an extent)
 * - a date filter is set
 *
 * @param query - The query object or query parameters
 * @internal
 */
export function isQueryCacheable(query: AttributeBinsQuery | Query | QueryProperties): boolean;

/**
 * @param layer
 * @internal
 */
export function getMaxRecords(layer?: Pick<FeatureLayer, "sourceJSON"> | SubtypeSublayer): number;

/**
 * Function building a where clause by concatenating a list of filters by using the AND operator.
 *
 * @param filterList - The list of filters to combine
 * @param operand - The operand to use to combine the filters (OR, AND...)
 * @internal
 */
export function combineFilters(filterList: (string | null | undefined)[], operand?: string): string;

/**
 * Computes the time extent to be used by the query.
 *
 * @param queryObject - The layer or feature layer view
 * @param defaultTimeExtent - The time extent defined at the series config level or provided at runtime
 * @internal
 */
export function getQueryTimeExtent(queryObject: QueryObject, defaultTimeExtent?: WebChartQuery["timeExtent"]): WebChartQuery["timeExtent"] | undefined;

/**
 * Computes the extent to be used by the query. We prioritize the feature layer view extent
 * over the series config extent, unless `ignoreViewExtent` is set to true.
 *
 * @param props - The layer or feature layer view
 * @internal
 */
export function getQueryGeometry(props: {
    queryObject: QueryObject;
    defaultGeometry?: WebChartQuery["geometry"];
    ignoreViewExtent?: boolean;
}): WebChartQuery["geometry"] | undefined;

/**
 * Transforms a [timestamp, timestamp] to a JSAPI TimeExtent object
 *
 * @param timeExtentConfig - The time extent filter from the config
 * @internal
 */
export function mapQueryTimeExtent(timeExtentConfig?: WebChartQuery["timeExtent"]): TimeExtent | undefined;

/**
 * Transforms a IGeometry to a JSAPI Geometry
 *
 * @param geometryConfig - The geometry from the config
 * @internal
 */
export function mapQueryGeometry(geometryConfig?: WebChartQuery["geometry"]): Geometry | null | undefined;

/**
 * Maps properties from a WebChartQuery and properties specific to temporal binning into an AttributeBinsQuery object.
 *
 * @param props - The layer or feature layer view
 * @internal
 */
export function mapAttributeBinsQueryForTemporalData(props: {
    queryObject?: QueryObject;
    queryConfig?: WebChartQuery;
    temporalBinning: WebChartTemporalBinning;
    dateField: string;
    splitByField?: string;
}): Promise<AttributeBinsQuery>;

/**
 * Builds a SQL expression as well as the start and end values necessary for the calendar date parts binning.
 *
 * @param props - The field used by the heat chart
 * @internal
 */
export function getCalendarDatePartsParameters(props: {
    field: string;
    fieldType?: RESTFieldType;
    unit?: string;
    addIntervalStatement: boolean;
    outTimeZone?: string;
    dataTimeZone?: string | null;
    runsOnClientQueryEngine?: boolean;
    addLeapDayExpression?: boolean;
}): {
    expression?: string;
    start?: number;
    end?: number;
};

/**
 * Maps properties from a WebChartQuery and properties specific to heat chart into an AttributeBinsQuery object.
 *
 * @param props - The layer or feature layer view
 * @internal
 */
export function mapAttributeBinsQueryForHeatChart(props: {
    queryObject?: QueryObject;
    queryConfig?: WebChartQuery;
    x: string;
    y: string;
    xTemporalBinning?: WebChartHeatChartSeries["xTemporalBinning"];
    yTemporalBinning?: WebChartHeatChartSeries["yTemporalBinning"];
    firstDayOfWeek?: number;
    configTimeZone?: string;
    includeLeapDay?: boolean;
    options?: ChartOptions;
}): Promise<AttributeBinsQuery>;

/**
 * Maps properties from a WebChartQuery and properties specific to temporal binning into an AttributeBinsQuery object.
 *
 * @param props - The layer or feature layer view
 * @internal
 */
export function mapAttributeBinsQueryForScatterplot(props: {
    queryObject?: QueryObject;
    queryConfig?: WebChartQuery;
    xStep: number;
    yStep: number;
    xMin: number;
    xMax: number;
    x: string;
    y: string;
}): AttributeBinsQuery;

/**
 * Maps properties from a WebChartQuery into a Query object.
 *
 * @param props - The layer or feature layer view
 * @internal
 */
export function mapQuery(props: {
    queryObject?: QueryObject;
    queryConfig?: WebChartQuery;
    maxRecordCountFactor?: number;
}): Query;

/**
 * @param layer
 * @internal
 */
export function getMaxRecordCountFactor(layer?: Pick<FeatureLayer, "sourceJSON"> | SubtypeSublayer): number | undefined;