import type FeatureLayer from "../layers/FeatureLayer.js";
import type UtilityNetwork from "./UtilityNetwork.js";
import type Circuit from "./support/Circuit.js";
import type CircuitExportJobInfo from "./support/CircuitExportJobInfo.js";
import type CircuitLocation from "./support/CircuitLocation.js";
import type CircuitVerifyJobInfo from "./support/CircuitVerifyJobInfo.js";
import type CircuitVerifyResult from "../rest/networks/circuits/support/CircuitVerifyResult.js";
import type { JSONSupport } from "../core/JSONSupport.js";
import type { CircuitExportResult, DomainNetworkJSON } from "./support/jsonTypes.js";
import type { CircuitHierarchy, CircuitStatus } from "./support/typeUtils.js";
import type { RequestOptions } from "../request/types.js";
import type { ExportCircuitsParametersProperties } from "../rest/networks/circuits/support/ExportCircuitsParameters.js";
import type { VerifyCircuitsParametersProperties } from "../rest/networks/circuits/support/VerifyCircuitsParameters.js";
import type { UtilityNetworkProperties } from "./UtilityNetwork.js";

export interface CircuitManagerProperties {
  /**
   * An object representing the telecom domain network in the
   * utility network data element.
   */
  telecomDomainNetwork?: DomainNetworkJSON;
  /** The [UtilityNetwork](https://developers.arcgis.com/javascript/latest/references/core/networks/UtilityNetwork/) that contains the telecom domain network being managed. */
  utilityNetwork?: UtilityNetworkProperties;
}

export interface CommonCircuitQueryProperties {
  hierarchy?: CircuitHierarchy;
  status?: CircuitStatus;
}

export interface QueryCircuitByNamesProperties extends CommonCircuitQueryProperties {
  names: string[];
  globalIds?: null;
  locations?: null;
  locationType?: null;
}

export interface QueryCircuitByIdsProperties extends CommonCircuitQueryProperties {
  names?: null;
  globalIds: string[];
  locations?: null;
  locationType?: null;
}

export interface QueryCircuitByLocationsProperties extends CommonCircuitQueryProperties {
  names?: null;
  globalIds?: null;
  locations: CircuitLocation[];
  locationType?: "start" | "stop" | "all" | null;
}

export type CircuitExportProperties = Pick<ExportCircuitsParametersProperties, "circuitNames" | "exportAcknowledgement" | "resultTypes" | "outSpatialReference">;

export type CircuitVerifyProperties = Pick<VerifyCircuitsParametersProperties, "circuitNames" | "forceVerify" | "synthesizeGeometries" | "outSpatialReference">;

/**
 * A CircuitManager provides access to circuit management capabilities for a telecom domain network
 * in a utility network.
 *
 * @since 4.34
 * @see [UtilityNetwork](https://developers.arcgis.com/javascript/latest/references/core/networks/UtilityNetwork/)
 * @see [UnitIdentifierManager](https://developers.arcgis.com/javascript/latest/references/core/networks/UnitIdentifierManager/)
 * @see [Telecom domain network](https://doc.esri.com/en/arcgis-pro/latest/help/data/utility-network/telecom-domain-networks.html)
 * @example
 * const utilityNetwork = new UtilityNetwork({
 *   layerUrl: "https://host.com/arcgis/rest/services/Test/FeatureServer/0",
 * });
 *
 * await utilityNetwork.load();
 *
 * const domainNetworks = utilityNetwork.dataElement?.domainNetworks;
 * const telecomDomainNetwork = domainNetworks.find((dn) => dn.isTelecomNetwork);
 *
 * const circuitManager = await utilityNetwork.getCircuitManager(telecomDomainNetwork.domainNetworkName);
 */
export default class CircuitManager extends JSONSupport {
  constructor(properties?: CircuitManagerProperties);
  /** A [FeatureLayer](https://developers.arcgis.com/javascript/latest/references/core/layers/FeatureLayer/) for the telecom domain network's circuit section table. */
  get circuitSectionTable(): FeatureLayer;
  /** A [FeatureLayer](https://developers.arcgis.com/javascript/latest/references/core/layers/FeatureLayer/) for the telecom domain network's circuit table. */
  get circuitTable(): FeatureLayer;
  /**
   * Returns the root feature service URL which the utility network is part of.
   *
   * @example `https://utilitynetwork.esri.com/server/rest/services/NapervilleElectric/FeatureServer/`
   */
  get featureServiceUrl(): string;
  /**
   * The version of the geodatabase of the feature service data used by the utility network.
   * Read the [Overview of versioning](https://doc.esri.com/en/arcgis-pro/latest/help/data/geodatabases/overview/overview-of-versioning-in-arcgis-pro.html)
   * topic for more details about this capability.
   */
  get gdbVersion(): string | null | undefined;
  /**
   * The utility network's historic moment to query.
   * If this property is not specified, queries will apply to the current features.
   */
  get historicMoment(): Date | null | undefined;
  /**
   * The URL of the network server.
   *
   * @example `https://utilitynetwork.esri.com/server/rest/services/NapervilleElectric/UtilityNetworkServer/`
   */
  get networkServiceUrl(): string;
  /** A [FeatureLayer](https://developers.arcgis.com/javascript/latest/references/core/layers/FeatureLayer/) for the telecom domain network's subcircuit table. */
  get subcircuitTable(): FeatureLayer;
  /**
   * An object representing the telecom domain network in the
   * utility network data element.
   */
  get telecomDomainNetwork(): DomainNetworkJSON;
  /** The name of the telecom domain network. */
  get telecomDomainNetworkName(): string;
  /** The [UtilityNetwork](https://developers.arcgis.com/javascript/latest/references/core/networks/UtilityNetwork/) that contains the telecom domain network being managed. */
  get utilityNetwork(): UtilityNetwork;
  /**
   * Modifies circuit information for an existing circuit in a telecom domain network.
   * This method replaces the existing circuit definition with the provided circuit.
   * If any properties are excluded from the provided circuit definition, it is removed from the circuit.
   *
   * To alter an existing circuit, the provided [Circuit](https://developers.arcgis.com/javascript/latest/references/core/networks/support/Circuit/) must
   * have a valid `globalId` property, else this method will throw an exception.
   *
   * @param circuit - The circuit to be altered.
   * @returns Resolves when the circuit is successfully altered.
   * @example
   * ```ts
   * const circuits = await circuitManager.queryCircuits(["FIRSTCIRCUIT"]);
   * circuits[0].name = "NewCircuitName";
   * await circuitManager.alter(circuits[0]);
   * ```
   */
  alter(circuit: Circuit): Promise<void>;
  /**
   * Creates a circuit in a telecom domain network.
   *
   * > [!WARNING]
   * >
   * > Circuits created during an active edit session will not be returned by a query until the session has been ended with `stopEditing`.
   *
   * @param circuit - The circuit to create.
   * @returns Resolves when the circuit is successfully created.
   * @example
   * ```ts
   * // Create a non-sectioned circuit with user-defined attributes.
   * const startingLocation = new CircuitLocation({
   *   sourceId: 20,
   *   globalId: "{8A1B5A33-3EBA-42CC-9085-31B22DAFE5DC}",
   *   firstUnit: 1,
   *   lastUnit: 1,
   * });
   *
   * const stoppingLocation = new CircuitLocation({
   *   sourceId: 20,
   *   globalId: "{F081B917-499E-43FC-AEC9-7C1B313BF128}",
   *   firstUnit: 1,
   *   lastUnit: 1,
   * });
   *
   * const attributes = {
   *   attributeOne: 1,
   *   attributeTwo: "Two",
   *   attributeThree: new Date().getTime(),
   *   attributeFour: null,
   * };
   *
   * const circuit = new Circuit({
   *   name: "FIRSTCIRCUIT",
   *   circuitType: "physical",
   *   startLocation: startingLocation,
   *   stopLocation: stoppingLocation,
   *   attributes: attributes,
   * });
   *
   * await circuitManager.create(circuit);
   * ```
   * @example
   * To create a sectioned circuit, provide a `Map` to represent the logical connectivity between
   * sections in a circuit. This map should represent a directed adjacency list where each key is
   * a `CircuitSection` that connects to other `CircuitSection` instances indicated by the key's
   * value. The map type is `Map<CircuitSection, CircuitSection[]>`.
   *
   * In this example, section 1 connects to 2 and 3 (where sections 2 and 3 are in parallel),
   * 2 connects to 4, 3 connects to 4, and 4 connects to nothing (it is the end of the circuit).
   * ```ts
   * // Create a sectioned circuit.
   * const sectionOne = new CircuitSection({
   *   sectionId: 1,
   *   sectionType: "physical",
   *   startLocation: new CircuitLocation({
   *     sourceId: 20,
   *     globalId: "{6B0A0E4E-80EF-4688-B463-253063A5B4B2}",
   *     firstUnit: 1,
   *     lastUnit: 4,
   *   }),
   *   stopLocation: new CircuitLocation({
   *     sourceId: 20,
   *     globalId: "{3A557124-4243-4615-96DF-51991E6B9766}",
   *     firstUnit: 1,
   *     lastUnit: 4,
   *   }),
   * });
   *
   * const sectionTwo = new CircuitSection({
   *   sectionId: 2,
   *   sectionType: "physical",
   *   subcircuit: new Subcircuit({ name: "SUBCIRCUITVALUE2" }),
   * });
   *
   * const sectionThree = new CircuitSection({
   *   sectionId: 3,
   *   sectionType: "physical",
   *   startLocation: new CircuitLocation({
   *     sourceId: 20,
   *     globalId: "{7C874691-D659-4311-B19C-D33027B6F48A}",
   *     firstUnit: 1,
   *     lastUnit: 4,
   *   }),
   *   stopLocation: new CircuitLocation({
   *     sourceId: 20,
   *     globalId: "{BF34887C-359E-4E00-A695-8D92BF41FE37}",
   *     firstUnit: 1,
   *     lastUnit: 4,
   *   }),
   * });
   *
   * const sectionFour = new CircuitSection({
   *   sectionId: 4,
   *   sectionType: "physical",
   *   startLocation: new CircuitLocation({
   *     sourceId: 20,
   *     globalId: "{E4ECA4B4-F9F7-4AB2-B2FD-6CDAB1A9506B}",
   *     firstUnit: 1,
   *     lastUnit: 4,
   *   }),
   *   stopLocation: new CircuitLocation({
   *     sourceId: 20,
   *     globalId: "{18DE7259-FDC6-4788-B13B-3F6210CCCB56}",
   *     firstUnit: 1,
   *     lastUnit: 4,
   *   }),
   * });
   *
   * const sections = new Map([
   *   [sectionOne, [sectionTwo, sectionThree]],
   *   [sectionTwo, [sectionFour]],
   *   [sectionThree, [sectionFour]],
   *   [sectionFour, []],
   * ]);
   *
   * const sectionedCircuit = new Circuit({
   *   name: "CIRCUIT - 1749681983401",
   *   circuitType: "physical",
   *   sections: sections,
   * });
   *
   * await circuitManager.create(sectionedCircuit);
   * ```
   */
  create(circuit: Circuit): Promise<void>;
  /**
   * Logically deletes one or more circuits in a telecom domain network.
   *
   * @param circuitNames - The names of the circuit or circuits to be deleted.
   * @returns Resolves when the specified circuits are successfully deleted.
   * @example
   * ```ts
   * const circuitNames = ["FIRSTCIRCUIT"];
   * await circuitManager.delete(circuitNames);
   * ```
   */
  delete(circuitNames: string[]): Promise<void>;
  /**
   * Exports feature and connectivity information about provided circuits in a telecom domain network
   * into JSON files for consumption by external systems. Each circuit exported is output to a separate JSON file.
   *
   * @param props - An object specifying configuration settings for the export.
   * @returns Resolves to an object
   *   specifying the export location and status for each circuit.
   * @example
   * ```ts
   * const circuits = await circuitManager.export({
   *   circuitNames: ["FIRSTCIRCUIT"],
   *   exportAcknowledgement: true,
   *   outSpatialReference: {
   *     wkid: 4326
   *   },
   *   resultTypes: [
   *     {
   *       type: "features",
   *       includeGeometry: true,
   *       includeDomainDescriptions: true,
   *       networkAttributeNames: ["Asset group", "Asset type"],
   *       diagramTemplateName: "",
   *       resultTypeFields: [
   *         { networkSourceId: 20, fieldName: "FIRSTUNIT" },
   *         { networkSourceId: 20, fieldName: "LASTUNIT" },
   *       ],
   *     },
   *   ],
   * });
   * ```
   */
  export(props: CircuitExportProperties): Promise<CircuitExportResult[]>;
  /**
   * Returns a [Circuit](https://developers.arcgis.com/javascript/latest/references/core/networks/support/Circuit/) instance
   * with its `circuitManager` property set to the current `CircuitManager` instance.
   *
   * @param circuitName - The name of the `Circuit` instance to create.
   * @param isSectioned - = false - Whether the `Circuit` instance is sectioned.
   * @returns A `Circuit` instance with its `circuitManager` property set to the current `CircuitManager` instance.
   */
  getCircuit(circuitName: string, isSectioned?: boolean): Circuit;
  /**
   * Loads the telecom domain network's circuit section table.
   *
   * @returns Resolves to a loaded [FeatureLayer](https://developers.arcgis.com/javascript/latest/references/core/layers/FeatureLayer/) for the circuit section table.
   */
  loadCircuitSectionTable(): Promise<FeatureLayer>;
  /**
   * Loads the telecom domain network's circuit table.
   *
   * @returns Resolves to a loaded [FeatureLayer](https://developers.arcgis.com/javascript/latest/references/core/layers/FeatureLayer/) for the circuit table.
   */
  loadCircuitTable(): Promise<FeatureLayer>;
  /**
   * Loads the telecom domain network's subcircuit table.
   *
   * @returns Resolves to a loaded [FeatureLayer](https://developers.arcgis.com/javascript/latest/references/core/layers/FeatureLayer/) for the subcircuit table.
   */
  loadSubcircuitTable(): Promise<FeatureLayer>;
  /**
   * Returns the names of circuits from a telecom domain network that satisfy a specified query.
   *
   * @param query - The query specifying the criteria for the circuits to return.
   * @returns The queried circuit names.
   * @example
   * ```ts
   * const props: QueryCircuitByLocationsProperties = {
   *   locations: [
   *     new CircuitLocation({
   *       sourceId: 20,
   *       globalId: "{8A1B5A33-3EBA-42CC-9085-31B22DAFE5DC}",
   *       firstUnit: 1,
   *       lastUnit: 1,
   *     }),
   *   ],
   *   locationType: "all",
   * };
   *
   * const circuitNames = await circuitManager.queryCircuitNames(props);
   * ```
   * @example
   * ```ts
   * const props: QueryCircuitByIdsProperties = {
   *   globalIds: ["{8A1B5A33-3EBA-42CC-9085-31B22DAFE5DC}"],
   * };
   *
   * const circuitNames = await circuitManager.queryCircuitNames(props);
   * ```
   */
  queryCircuitNames(query: QueryCircuitByLocationsProperties | QueryCircuitByIdsProperties): Promise<string[]>;
  /**
   * Returns circuits from a telecom domain network that satisfy a specified query.
   * The query can specify circuit names, globalIds, or start/stop locations, along with additional options such as circuit hierarchy and status.
   *
   * @param query - The names, globalIds, or start/stop locations of the circuits to query.
   * @returns The queried circuits.
   * @example
   * ```ts
   * // Query circuits by locations.
   * const circuits = await circuitManager?.queryCircuits({
   *   hierarchy: "consumers-and-providers",
   *   locations: [
   *     new CircuitLocation({
   *       firstUnit: 1,
   *       globalId: "{B8E64696-E9C5-4349-ADC8-E72BBF2797D1}",
   *       lastUnit: 1,
   *       sourceId: 20,
   *     }),
   *   ],
   * });
   * ```
   * @example
   * ```ts
   * // Query circuits by name.
   * const circuits = await circuitManager.queryCircuits({ names: ["MULTISECTIONCIRCUIT"] });
   * ```
   * @example
   * ```ts
   * // Query circuits by globalIds.
   * const circuits = await circuitManager.queryCircuits({ globalIds: ["{8A1B5A33-3EBA-42CC-9085-31B22DAFE5DC}"] });
   * ```
   */
  queryCircuits(query: QueryCircuitByNamesProperties | QueryCircuitByLocationsProperties | QueryCircuitByIdsProperties): Promise<Circuit[]>;
  /**
   * Asynchronously exports feature and connectivity information about provided circuits in a telecom domain network.
   *
   * @param props - An object specifying configuration settings for the export job.
   * @param options - The request options specified by the user in the data request.
   * @returns Resolves to a [CircuitExportJobInfo](https://developers.arcgis.com/javascript/latest/references/core/networks/support/CircuitExportJobInfo/) object with the results of the export job.
   * @since 5.1
   * @example
   * ```ts
   * const exportJob = await circuitManager.submitExportJob({
   *   circuitNames: ["MULTISECTIONCIRCUIT"],
   *   exportAcknowledgement: true,
   *   outSpatialReference: {
   *     wkid: 4326,
   *   },
   *   resultTypes: [
   *     {
   *       type: "features",
   *       includeGeometry: true,
   *       includeDomainDescriptions: true,
   *       networkAttributeNames: ["Asset group", "Asset type"],
   *       diagramTemplateName: "",
   *       resultTypeFields: [
   *         { networkSourceId: 20, fieldName: "FIRSTUNIT" },
   *         { networkSourceId: 20, fieldName: "LASTUNIT" },
   *       ],
   *     },
   *   ],
   * });
   *
   * await exportJob.waitForJobCompletion();
   * ```
   */
  submitExportJob(props: CircuitExportProperties, options?: RequestOptions | null | undefined): Promise<CircuitExportJobInfo>;
  /**
   * Asynchronously checks the validity of circuits in a telecom domain network.
   *
   * @param props - An object specifying configuration settings for the verify job.
   * @param options - The request options specified by the user in the data request.
   * @returns Resolves to a [CircuitVerifyJobInfo](https://developers.arcgis.com/javascript/latest/references/core/networks/support/CircuitVerifyJobInfo/) object with the results of the verify job.
   * @since 5.1
   * @example
   * ```ts
   * const props: VerifyCircuitsProperties = {
   *   circuitNames: ["FIRSTCIRCUIT"],
   *   forceVerify: true,
   *   synthesizeGeometries: true,
   * };
   *
   * const verifyCircuitsResult = await circuitManager.submitVerifyJob(props);
   * ```
   */
  submitVerifyJob(props: CircuitVerifyProperties, options?: RequestOptions | null | undefined): Promise<CircuitVerifyJobInfo>;
  /**
   * Checks the validity of circuits in a telecom domain network.
   * The operation confirms that a circuit can be traced from the starting location to the stopping location
   * and ensures that circuit sections and subcircuits are properly configured.
   *
   * @param props - An object specifying configuration settings for the verify operation.
   * @returns Resolves to an array of objects specifying the verification status for each circuit.
   * @example
   * ```ts
   * const props: VerifyCircuitsProperties = {
   *   circuitNames: ["FIRSTCIRCUIT"],
   *   outSpatialReference: {
   *     wkid: 4326,
   *   },
   *   forceVerify: true,
   *   synthesizeGeometries: true,
   * };
   *
   * const verifyCircuitsResult = await circuitManager.verify(props);
   * ```
   */
  verify(props: CircuitVerifyProperties): Promise<CircuitVerifyResult[]>;
}