import type Accessor from "../../core/Accessor.js";
import type Collection from "../../core/Collection.js";
import type VersioningState from "../../versionManagement/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 "../../versionManagement/support/jsonTypes.js";
import type { AccessType } from "../../versionManagement/support/type.js";
import type { VersionAdapter } from "../../versionManagement/versionAdapters/types.js";

export interface VersionManagementViewModelProperties extends Partial<Pick<VersionManagementViewModel, "featureServiceLookup" | "serverVersionLookup" | "serviceNameLookup" | "userLookup" | "versionAdministratorLookup" | "versioningStateLookup" | "versioningStates" | "view">> {}

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

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

export type VersionManagementViewModelExecutionError = "no-feature-service-found" | "no-valid-enterprise-version" | "no-valid-version-name" | "no-version-management-service-found" | undefined;

export type VersionManagementViewModelLoadError = "no-feature-services" | "no-layers-property" | undefined;

export type VersionManagementViewModelState = "loading" | "ready" | "executing" | "success" | "failed" | "disabled";

/**
 * This class allows you to manage versions from a variety of [feature services](https://developers.arcgis.com/javascript/latest/api-reference/esri-rest-featureService-FeatureService.html).
 * The VersionManagementViewModel allows you to alter, create, delete versions etc. provided that a `featureServiceUrl` is provided for these operations.
 *
 * @deprecated since version 5.0. Use [VersionManager](https://developers.arcgis.com/javascript/latest/api-reference/esri-versionManagement-VersionManager.html) instead since the [VersionManagementViewModel](https://developers.arcgis.com/javascript/latest/api-reference/esri-widgets-VersionManagement-VersionManagementViewModel.html) will be removed in 6.0.
 * @since 4.29
 * @see [VersionManager](https://developers.arcgis.com/javascript/latest/api-reference/esri-versionManagement-VersionManager.html)
 * @see [UtilityNetwork](https://developers.arcgis.com/javascript/latest/api-reference/esri-networks-UtilityNetwork.html)
 * @see [VersionManagementService](https://developers.arcgis.com/javascript/latest/api-reference/esri-versionManagement-VersionManagementService.html)
 * @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 viewModel = new VersionManagementViewModel({ view });
 * await whenOnce(() => viewModel.state === "ready");
 */
export default class VersionManagementViewModel extends Accessor {
  constructor(properties?: VersionManagementViewModelProperties);
  /** Displays execution errors. */
  get executionError(): VersionManagementViewModelExecutionError | null | undefined;
  /** A key-value pair of [FeatureServiceResourcesBundle](https://developers.arcgis.com/javascript/latest/api-reference/esri-rest-featureService-types.html#FeatureServiceResourcesBundle). */
  accessor featureServiceLookup: Map<string, FeatureServiceResourcesBundle>;
  /** Displays an error if loading fails. */
  get loadError(): VersionManagementViewModelLoadError | null | undefined;
  /** Map of Service URLs and enterprise versions. */
  accessor serverVersionLookup: Map<string, number>;
  /** Map of Service URLs and service names. Keeps track of all the [FeatureService](https://developers.arcgis.com/javascript/latest/api-reference/esri-rest-featureService-FeatureService.html) instances in the [VersionManagementService](https://developers.arcgis.com/javascript/latest/api-reference/esri-versionManagement-VersionManagementService.html) class instance. */
  accessor serviceNameLookup: Map<string, string>;
  /** The viewModel's state. */
  get state(): VersionManagementViewModelState;
  /** Map of Service URLs and logged in users . */
  accessor userLookup: Map<string, string>;
  /** This property determines if a user has version admin privileges. */
  accessor versionAdministratorLookup: Map<string, boolean>;
  /** This property contains metadata about the versioning state. */
  accessor versioningStateLookup: Map<string, VersioningState>;
  accessor versioningStates: Collection<VersioningState>;
  /** The view from which the widget will operate. */
  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://enterprise.arcgis.com/en/get-started/latest/windows/what-is-arcgis-enterprise-.htm) version 11.2 or higher.
   *
   * @param parameters - Parameters used to alter a version.
   * @returns When resolved, returns `true` if the alter operation completes successfully.
   * @example
   * await versionManagementViewModel.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.
   * @example
   * await versionManagementViewModel.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.
   * @example
   * await viewModel.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://enterprise.arcgis.com/en/get-started/latest/windows/what-is-arcgis-enterprise-.htm) 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.
   * @example
   * await versionManagementViewModel.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`.
   * @example const versionInfos = await versionManagementViewModel.getVersionInfos("https://myHostName.domain.com/arcgis/rest/services/TestService_11_2/FeatureServer/0");
   */
  getVersionInfos(featureServerUrl: string): Promise<VersionInfo[]>;
}