import type Accessor from "../core/Accessor.js";
import type Collection from "../core/Collection.js";
import type VersioningState from "./VersioningState.js";
import type MapView from "../views/MapView.js";
import type { FeatureServiceResourcesBundle } from "../rest/featureService/types.js";
import type { ServiceResult, VersionIdentifier, VersionInfo, VersionInfoExtended as VersionInfoExtendedJSON } from "./support/jsonTypes.js";
import type { AccessType } from "./support/type.js";
import type { VersionAdapter } from "./versionAdapters/types.js";

/** @since 5.0 */
export interface VersionManagerProperties extends Partial<Pick<VersionManager, "featureServiceLookup" | "serverVersionLookup" | "serviceNameLookup" | "userLookup" | "versionAdministratorLookup" | "versioningStateLookup" | "versioningStates" | "view">> {}

/**
 * Parameters used to alter a version.
 *
 * @since 5.0
 */
export interface AlterVersionParameters {
  /**
   * The url of a feature service.
   *
   * @since 5.0
   */
  featureServerUrl: string;
  /**
   * The Identifier of a version.
   *
   * @since 5.0
   */
  versionIdentifier: VersionIdentifier;
  /**
   * The new owner name of the version.
   *
   * @since 5.0
   */
  ownerName?: string;
  /**
   * The new name for the version.
   *
   * @since 5.0
   */
  versionName?: string;
  /**
   * The new access permissions of the version.
   *
   * @since 5.0
   */
  access?: AccessType;
  /**
   * The new description for the version.
   *
   * @since 5.0
   */
  description?: string;
}

/**
 * Parameters used to create a new version.
 *
 * @since 5.0
 */
export interface CreateVersionParameters {
  /**
   * The url of a feature service.
   *
   * @since 5.0
   */
  featureServerUrl: string;
  /**
   * The name of the new version.
   *
   * @since 5.0
   */
  versionName: string;
  /**
   * The access type of the new version.
   *
   * @since 5.0
   */
  access: AccessType;
  /**
   * The description of the new version.
   *
   * @since 5.0
   */
  description: string;
  /**
   * The version owner.
   *
   * @since 5.0
   */
  ownerName?: string;
}

/** @since 5.0 */
export type VersionManagerExecutionError = "no-feature-service-found" | "no-valid-enterprise-version" | "no-valid-version-name" | "no-version-management-service-found" | undefined;

/** @since 5.0 */
export type VersionManagerLoadError = "no-feature-services" | "no-layers-property" | undefined;

/** @since 5.0 */
export type VersionManagerState = "loading" | "ready" | "executing" | "failed" | "disabled";

/**
 * This class allows you to manage versions from a variety of [feature services](https://developers.arcgis.com/javascript/latest/references/core/rest/featureService/FeatureService/).
 * The VersionManager allows you to alter, create, delete versions etc. provided that a `featureServiceUrl` is provided for these operations.
 *
 * @since 5.0
 * @see [UtilityNetwork](https://developers.arcgis.com/javascript/latest/references/core/networks/UtilityNetwork/)
 * @see [VersionManagementService](https://developers.arcgis.com/javascript/latest/references/core/versionManagement/VersionManagementService/)
 * @example
 * const webMap = new WebMap({
 *     portalItem: {
 *     id: "webmapID"
 *   }
 * });
 *
 * const view = new MapView({
 *     map: webMap
 * });
 *
 * featureLayer = new FeatureLayer({
 *     url: "https://myHostName.domain.com/arcgis/rest/services/TestService_11_2/FeatureServer/0",
 * });
 *
 * webMap.layers.add(featureLayer);
 *
 * const versionManager = new VersionManager({ view });
 *
 * // Wait for the version manager instance to be ready before performing operations.
 * await whenOnce(() => versionManager.state === "ready");
 */
export default class VersionManager extends Accessor {
  /** @since 5.0 */
  constructor(properties?: VersionManagerProperties);
  /**
   * Displays execution errors.
   *
   * @since 5.0
   */
  get executionError(): VersionManagerExecutionError | null | undefined;
  /**
   * A key-value pair of [FeatureServiceResourcesBundle](https://developers.arcgis.com/javascript/latest/references/core/rest/featureService/types/#FeatureServiceResourcesBundle).
   *
   * @since 5.0
   */
  accessor featureServiceLookup: Map<string, FeatureServiceResourcesBundle>;
  /**
   * Displays an error if loading fails.
   *
   * @since 5.0
   */
  get loadError(): VersionManagerLoadError | null | undefined;
  /**
   * Map of Service URLs and enterprise versions.
   *
   * @since 5.0
   */
  accessor serverVersionLookup: Map<string, number>;
  /**
   * Map of Service URLs and service names. Keeps track of all the [FeatureService](https://developers.arcgis.com/javascript/latest/references/core/rest/featureService/FeatureService/) instances in the [VersionManagementService](https://developers.arcgis.com/javascript/latest/references/core/versionManagement/VersionManagementService/) class instance.
   *
   * @since 5.0
   */
  accessor serviceNameLookup: Map<string, string>;
  /**
   * The current state of this object.
   *
   * | Value | Description |
   * | ----- |------------ |
   * | disabled | An error occured during initialization. |
   * | executing | An operation is being performed. |
   * | failed | An error occurred during execution. |
   * | loading | The object is loading. |
   * | ready | Object loaded successfully or operation completed successfully. All items in [versioningStates](https://developers.arcgis.com/javascript/latest/references/core/versionManagement/VersionManager/#versioningStates) are loaded. |
   *
   * @since 5.0
   */
  get state(): VersionManagerState;
  /**
   * Map of Service URLs and logged in users .
   *
   * @since 5.0
   */
  accessor userLookup: Map<string, string>;
  /**
   * This property determines if a user has version admin privileges.
   *
   * @since 5.0
   */
  accessor versionAdministratorLookup: Map<string, boolean>;
  /**
   * This property contains metadata about the versioning state.
   *
   * @since 5.0
   */
  accessor versioningStateLookup: Map<string, VersioningState>;
  /** @since 5.0 */
  accessor versioningStates: Collection<VersioningState>;
  /**
   * This property defines the target [MapView](https://developers.arcgis.com/javascript/latest/references/core/views/MapView/).
   *
   * @since 5.0
   */
  accessor view: MapView;
  /**
   * The alter operation allows you to change the geodatabase version's name, description, owner, and access permissions.
   *
   * > [!CAUTION]
   * >
   * > **License**
   * >
   * > This method requires the feature service and version management service to be published with [ArcGIS Enterprise](https://doc.esri.com/en/arcgis-enterprise/latest/introduction/what-is-arcgis-enterprise-.html) version 11.2 or higher.
   *
   * @param parameters - Parameters used to alter a version.
   * @returns When resolved, returns `true` if the alter operation completes successfully.
   * @since 5.0
   * @example
   * await versionManager.alterVersion({
   *   featureServiceUrl: "https://myHostName.domain.com/arcgis/rest/services/TestService_11_2/FeatureServer/0",
   *   versionIdentifier: {
   *   guid: myVersion.versionIdentifier.guid,
   *   name: myVersion.versionIdentifier.name,
   * },
   *   versionName: "updatedVersionName"
   * });
   */
  alterVersion(parameters: AlterVersionParameters): Promise<boolean>;
  /**
   * Method used to change a version using a featureServerUrl, name, and guid of a version.
   *
   * @param featureServerUrl - The url of a feature service.
   * @param toVersionName - Incoming version name.
   * @param toVersionGuid - Incoming version guid.
   * @returns When resolved, returns a map of version adapter to result.
   * @since 5.0
   * @example
   * await versionManager.changeVersion(
   *    "https://myHostName.domain.com/arcgis/rest/services/TestService_11_2/FeatureServer/0",
   *    "incomingVersionName",
   *    "incomingVersionGuid"
   *  )
   */
  changeVersion(featureServerUrl: string, toVersionName: string, toVersionGuid: string): Promise<Map<VersionAdapter, ServiceResult>>;
  /**
   * Creates a new version given the following parameters.
   *
   * @param parameters - Parameters used to create a new version.
   * @returns When the promise is resolved, the VersionInfoExtendedJSON will be returned once the create operation is successfully completed.
   * @since 5.0
   * @example
   * await versionManager.createVersion({
   *     featureServerUrl: "https://myHostName.domain.com/arcgis/rest/services/TestService_11_2/FeatureServer/0",
   *     versionName: "NewVersionName",
   *     description: "New Version Description",
   *     access: "public",
   * });
   */
  createVersion(parameters: CreateVersionParameters): Promise<VersionInfoExtendedJSON>;
  /**
   * Deletes a version given the following parameters.
   *
   * > [!CAUTION]
   * >
   * > **License**
   * >
   * > This method requires the feature service and version management service to be published with [ArcGIS Enterprise](https://doc.esri.com/en/arcgis-enterprise/latest/introduction/what-is-arcgis-enterprise-.html) version 11.2 or higher.
   *
   * @param featureServerUrl - The url of a feature service.
   * @param versionName - The name of the version that is to be deleted.
   * @param versionGuid - The guid of the version that is to be deleted.
   * @returns When resolved, returns `true` if the delete operation completes successfully.
   * @since 5.0
   * @example
   * await versionManager.deleteVersion(
   *   "https://myHostName.domain.com/arcgis/rest/services/TestService_11_2/FeatureServer/0",
   *   "versionName",
   *   "{45A4CF5B-69FB-4D94-96F7-25F92EB4C0EC}"
   * );
   */
  deleteVersion(featureServerUrl: string, versionName: string, versionGuid: string): Promise<boolean>;
  /**
   * Returns all versions accessible to the currently logged-in user.
   *
   * @param featureServerUrl - The url of a feature service.
   * @returns When resolved, returns an array of `VersionInfo`.
   * @since 5.0
   * @example const versionInfos = await versionManager.getVersionInfos("https://myHostName.domain.com/arcgis/rest/services/TestService_11_2/FeatureServer/0");
   */
  getVersionInfos(featureServerUrl: string): Promise<VersionInfo[]>;
}