/**
 * Feature utils for Components.
 *
 * @internal
 * @internal
 */
import type WebScene from "../../WebScene.js";
import type MapClass from "../../Map.js";
import type FeatureLayer from "../../layers/FeatureLayer.js";
import type SubtypeGroupLayer from "../../layers/SubtypeGroupLayer.js";
import type Relationship from "../../layers/support/Relationship.js";
import type UtilityNetwork from "../../networks/UtilityNetwork.js";
import type Portal from "../../portal/Portal.js";
import type Query from "../../rest/support/Query.js";
import type { AbortOptions } from "../../core/promiseUtils.js";
import type { ProjectOptions } from "../../geometry/operators/types.js";
import type { RequestOptions } from "../../request/types.js";

/**
 * Finds a related layer for a given layer and relationship info.
 *
 * @param map - The map containing the layers.
 * @param layer - The layer to find relationships for.
 * @param relationship - The relationship info to use for finding related layers.
 * @returns The related layer, if found.
 * @internal
 * @internal
 */
export function findRelatedLayer(map: MapClass | WebScene, layer: any, relationship: Relationship): any | null | undefined;

/**
 * Determines if a layer is both relatable and feature-supported.
 *
 * @param layer - A layer to check.
 * @returns True if the layer is relatable and feature-supported.
 * @internal
 * @internal
 */
export function isRelatableFeatureSupportedLayer(layer: unknown): boolean;

/**
 * Determines if a layer supports relationships.
 *
 * @param layer - A layer to check.
 * @returns True if the layer is relatable.
 * @internal
 * @internal
 */
export function isRelatableLayer(layer: unknown): boolean;

/**
 * Determines if a layer is a feature-supported layer.
 *
 * @param layer - A layer to check.
 * @returns True if the layer is feature-supported.
 * @internal
 * @internal
 */
export function isFeatureSupportedLayer(layer: unknown): boolean;

/**
 * Used to find an instance of [UtilityNetwork](https://developers.arcgis.com/javascript/latest/references/core/networks/UtilityNetwork/).
 *
 * @param map - Map that contains a [UtilityNetwork](https://developers.arcgis.com/javascript/latest/references/core/networks/UtilityNetwork/).
 * @param layer - The layer being validated as a UtilityLayer.
 * @returns Returns a [UtilityNetwork](https://developers.arcgis.com/javascript/latest/references/core/networks/UtilityNetwork/).
 * @internal
 * @internal
 */
export function findUtilityNetwork(map: MapClass, layer: any): UtilityNetwork | null | undefined;

/**
 * Retrieves all features in a layer matching a given [Query](https://developers.arcgis.com/javascript/latest/references/core/rest/support/Query/).
 * This method executes the query in a loop, incrementing the query's [Query.start](https://developers.arcgis.com/javascript/latest/references/core/rest/support/Query/#start)
 * when necessary to overcome transfer limits.
 *
 * Each query uses the layer's maximum query size for [Query.num](https://developers.arcgis.com/javascript/latest/references/core/rest/support/Query/#num).
 *
 * @param layer - The layer to query.
 * @param query - Specifies the attributes and spatial filter of the query.
 * @param options - The request options.
 * @returns When resolved, the JSON object representing a [FeatureSet](https://developers.arcgis.com/javascript/latest/references/core/rest/support/FeatureSet/) is returned.
 * @internal
 * @internal
 */
export function queryAllJSON(layer: FeatureLayer | SubtypeGroupLayer, query: Query, options?: RequestOptions): Promise<unknown>;

/**
 * Returns the URL of the ArcGIS Enterprise portal that owns the given service.
 *
 * @param serviceUrl - The URL of the service.
 * @param options - Optional abort options for cancelling the request.
 * @returns A promise that resolves to the owning portal URL, or `null` if it cannot be determined.
 * @internal
 * @internal
 */
export function getOwningPortalUrl(serviceUrl: string, options?: AbortOptions | null | undefined): Promise<string | null>;

/**
 * Returns whether a portal user has a given user type extension.
 *
 * @param portal - The portal that the user belongs to.
 * @param userName - The username to evaluate.
 * @param userTypeExtensionName - The user type extension name to check.
 * @returns A promise that resolves to `true` when the user has the extension, otherwise `false`.
 * @internal
 * @internal
 */
export function hasUserTypeExtension(portal: Portal, userName: string, userTypeExtensionName: string): Promise<boolean>;

/**
 * Finds an item in the specified map or generates a new value if it does not exist.
 *
 * @param map - The map to search.
 * @param key - The key to look up.
 * @param createValue - Factory function that creates the value if the key does not exist.
 * @returns The existing value in the map, or a newly created value.
 * @internal
 * @internal
 */
export function getOrCreateMapValue<TKey, TValue>(map: Map<TKey, TValue>, key: TKey, createValue: () => TValue): TValue;

/**
 * Used to generate a new reactive map that implements the Map interface.
 *
 * @returns A Map instance with reactivity features applied.
 * @internal
 * @internal
 */
export function createReactiveMap<Key, Value>(): Map<Key, Value>;

/**
 * Initializes projection support between two spatial references. Ensures that the projection engine is ready to project geometries
 * between the specified source and destination spatial references.
 *
 * @param source - The source spatial reference or well-known ID.
 * @param dest - The destination spatial reference or well-known ID.
 * @param options - Optional projection options.
 * @param abortOptions - Optional abort options to cancel the operation.
 * @returns A promise that resolves when the projection engine is initialized.
 * @internal
 * @internal
 */
export function initializeProjection(source: any | null | undefined, dest: any | null | undefined, options?: ProjectOptions | null | undefined, abortOptions?: AbortOptions | null | undefined): Promise<void>;