import type Graphic from "../../Graphic.js";
import type RouteLayer from "../../layers/RouteLayer.js";
import type PortalItem from "../../portal/PortalItem.js";
import type DirectionLine from "../../rest/support/DirectionLine.js";
import type DirectionPoint from "../../rest/support/DirectionPoint.js";
import type NetworkAttribute from "../../rest/support/NetworkAttribute.js";
import type NetworkServiceDescription from "../../rest/support/NetworkServiceDescription.js";
import type PointBarrier from "../../rest/support/PointBarrier.js";
import type PolygonBarrier from "../../rest/support/PolygonBarrier.js";
import type PolylineBarrier from "../../rest/support/PolylineBarrier.js";
import type RouteInfo from "../../rest/support/RouteInfo.js";
import type RouteParameters from "../../rest/support/RouteParameters.js";
import type Stop from "../../rest/support/Stop.js";
import type TravelMode from "../../rest/support/TravelMode.js";
import type { EventedAccessor } from "../../core/Evented.js";
import type { GeometryUnion } from "../../geometry/types.js";
import type { RouteLayerSolveResult, LayerSaveAsOptions } from "../../layers/types.js";
import type { MapViewOrSceneView } from "../../views/MapViewOrSceneView.js";
import type { SketchUpdateEventState } from "../Sketch/types.js";
import type { GoTo, GoToProperties } from "../support/GoTo.js";
import type { RouteParametersProperties } from "../../rest/support/RouteParameters.js";
import type { TravelModeProperties } from "../../rest/support/TravelMode.js";

export interface DirectionsViewModelProperties extends GoToProperties, Partial<Pick<DirectionsViewModel, "apiKey" | "autoSolve" | "autoSolveOn" | "layer" | "maxStops" | "view">> {
  /**
   * Route Parameters object used to call the service.
   * Please refer to the [RouteParameters](https://developers.arcgis.com/javascript/latest/references/core/rest/support/RouteParameters/)
   * documentation for the list of available settings.
   */
  routeParameters?: RouteParametersProperties;
  /**
   * The [travel mode](https://developers.arcgis.com/javascript/latest/references/core/rest/support/TravelMode/) that will be used by [getDirections()](https://developers.arcgis.com/javascript/latest/references/core/widgets/Directions/DirectionsViewModel/#getDirections)
   * when requesting the route and directions.
   *
   * For a list of available travel modes please access [travelModes](https://developers.arcgis.com/javascript/latest/references/core/widgets/Directions/DirectionsViewModel/#travelModes) or the `supportedTravelModes`
   * property on the [serviceDescription](https://developers.arcgis.com/javascript/latest/references/core/widgets/Directions/DirectionsViewModel/#serviceDescription).
   *
   * If the [RouteLayer](https://developers.arcgis.com/javascript/latest/references/core/layers/RouteLayer/) assigned to [layer](https://developers.arcgis.com/javascript/latest/references/core/widgets/Directions/DirectionsViewModel/#layer) is hosted on ArcGIS Online and ArcGIS
   * Enterprise then this property will attempt to assign the previously used travel mode.
   *
   * By default, if the [layer](https://developers.arcgis.com/javascript/latest/references/core/widgets/Directions/DirectionsViewModel/#layer) is not an ArcGIS Online and ArcGIS Enterprise item, this property will be to
   * routing service's default travel mode (see `defaultTravelMode` of [NetworkServiceDescription](https://developers.arcgis.com/javascript/latest/references/core/rest/support/NetworkServiceDescription/)).
   *
   * @see [Default travel modes](https://doc.arcgis.com/en/arcgis-online/reference/travel-modes.htm#GUID-96DF7F50-E0B2-4BF3-8271-EB515D3F0107)
   * @example
   * // Create a RouteLayer and assign to the DirectionsViewModel.
   * const layer = new RouteLayer();
   * map.add(layer);
   *
   * const apiKey = "<your api key>";
   * const directionsViewModel = new DirectionsViewModel({ apiKey, layer });
   * await directionsViewModel.load(); // wait for the view model to load the route service's "service description".
   *
   * // Print view model's selected travel mode. This will be equivalent to the routing service's default travel mode.
   * console.log(directionsViewModel.selectedTravelMode.name);
   *
   * // Assign the "Walking Time" travel mode.
   * directionsViewModel.selectedTravelMode = directionsViewModel.travelModes.find(({ name }) => name === "Walking Time");
   */
  selectedTravelMode?: TravelModeProperties | null;
}

export type State = "disabled" | "error" | "initializing" | "ready" | "routing" | "unauthenticated";

export type AutoSolveState = Exclude<SketchUpdateEventState, "start">;

/**
 * Provides the communication and data manipulation logic for the [Directions](https://developers.arcgis.com/javascript/latest/references/core/widgets/Directions/) widget and [component](https://developers.arcgis.com/javascript/latest/references/map-components/components/arcgis-directions/).
 *
 * @since 4.6
 * @see [Directions](https://developers.arcgis.com/javascript/latest/references/core/widgets/Directions/) widget
 * @see [Directions component](https://developers.arcgis.com/javascript/latest/references/map-components/components/arcgis-directions/)
 * @see [Guide topic - Proxy pages](https://developers.arcgis.com/javascript/latest/proxies/)
 * @see [Sample - Directions widget](https://developers.arcgis.com/javascript/latest/sample-code/widgets-directions/)
 * @see [Programming patterns: Widget viewModel pattern](https://developers.arcgis.com/javascript/latest/programming-patterns/#widget-viewmodel-pattern)
 * @example
 * const layer = new RouteLayer();
 * map.add(layer);
 *
 * // Create and instantiate the DirectionsViewModel with an API key and the RouteLayer.
 * // Use `load()` to load the view model's routing resources including the service description associated with the route layer's routing service.
 * const apiKey = "<your api key>";
 * const directionsViewModel = new DirectionsViewModel({ apiKey, layer });
 * await directionsViewModel.load();
 */
export default class DirectionsViewModel extends DirectionsViewModelSuperclass {
  constructor(properties?: DirectionsViewModelProperties);
  /**
   * An authorization string used to access a resource or service.
   * [API keys](https://developers.arcgis.com/documentation/security-and-authentication/api-key-authentication/) are generated
   * and managed in the portal. An API key is tied
   * explicitly to an ArcGIS account; it is also used to monitor service usage.
   * Setting a fine-grained API key on a specific class overrides the [global API key](https://developers.arcgis.com/javascript/latest/references/core/config/#Config-apiKey).
   *
   * By default, the following URLs will be used (unless overwritten in the app, or if using different defaults from a portal):
   *
   * Geocoding URL: `https://geocode-api.arcgis.com/arcgis/rest/services/World/GeocodeServer`
   *
   * Routing URL: `https://route-api.arcgis.com/arcgis/rest/services/World/Route/NAServer/Route_World`
   *
   * @since 4.19
   */
  accessor apiKey: string | null | undefined;
  /**
   * When `true`, the assigned route layer will automatically solve whenever the stops or barriers (if any) are edited.
   * The default value is `true`. Setting this property to `false` may be useful for complex routes that take a long
   * time to solve.
   *
   * @default true
   * @since 4.32
   */
  accessor autoSolve: boolean;
  /**
   * When [autoSolve](https://developers.arcgis.com/javascript/latest/references/core/widgets/Directions/DirectionsViewModel/#autoSolve) is `true`, this property defines when a route will be re-solved.
   *
   * When `"complete"` is included the route will only re-solved once the interactive operation is complete. This is
   * normally when the selected network feature or features are deselected.
   *
   * When `"active"` is included the route will re-solve continuously as the interactive operation is ongoing (e.g.,
   * while dragging a stop or waypoint).
   *
   * By default, the route will only re-solve when the interactive operation is complete.
   *
   * @since 5.0
   */
  accessor autoSolveOn: AutoSolveState[];
  /**
   * The network attribute name to be used as the impedance attribute in the analysis. The
   * value is defined in the specific routing network layer used in the
   * [route](https://developers.arcgis.com/javascript/latest/references/core/rest/route/).
   *
   * For more information, see [Understanding the network attribute](https://resources.arcgis.com/en/help/main/10.2/index.html#//00470000000m000000).
   */
  get impedanceAttribute(): NetworkAttribute | null | undefined;
  /**
   * The most recent route result. Returns a [RouteLayerSolveResult](https://developers.arcgis.com/javascript/latest/references/core/layers/types/#RouteLayerSolveResult)
   * object containing properties for barriers (if any), stops, and directions.
   *
   * @see [RouteLayer.solve()](https://developers.arcgis.com/javascript/latest/references/core/layers/RouteLayer/#solve)
   */
  get lastRoute(): RouteLayerSolveResult | null | undefined;
  /**
   * The [RouteLayer](https://developers.arcgis.com/javascript/latest/references/core/layers/RouteLayer/) associated with the DirectionsViewModel. The route layer contains stops
   * and barriers and will be used to display and solve routes.
   *
   * @since 4.24
   */
  accessor layer: RouteLayer | null | undefined;
  /**
   * The maximum number of stops allowed for routing.
   *
   * @default 50
   */
  accessor maxStops: number;
  /**
   * Route Parameters object used to call the service.
   * Please refer to the [RouteParameters](https://developers.arcgis.com/javascript/latest/references/core/rest/support/RouteParameters/)
   * documentation for the list of available settings.
   */
  get routeParameters(): RouteParameters;
  set routeParameters(value: RouteParametersProperties);
  /**
   * The [travel mode](https://developers.arcgis.com/javascript/latest/references/core/rest/support/TravelMode/) that will be used by [getDirections()](https://developers.arcgis.com/javascript/latest/references/core/widgets/Directions/DirectionsViewModel/#getDirections)
   * when requesting the route and directions.
   *
   * For a list of available travel modes please access [travelModes](https://developers.arcgis.com/javascript/latest/references/core/widgets/Directions/DirectionsViewModel/#travelModes) or the `supportedTravelModes`
   * property on the [serviceDescription](https://developers.arcgis.com/javascript/latest/references/core/widgets/Directions/DirectionsViewModel/#serviceDescription).
   *
   * If the [RouteLayer](https://developers.arcgis.com/javascript/latest/references/core/layers/RouteLayer/) assigned to [layer](https://developers.arcgis.com/javascript/latest/references/core/widgets/Directions/DirectionsViewModel/#layer) is hosted on ArcGIS Online and ArcGIS
   * Enterprise then this property will attempt to assign the previously used travel mode.
   *
   * By default, if the [layer](https://developers.arcgis.com/javascript/latest/references/core/widgets/Directions/DirectionsViewModel/#layer) is not an ArcGIS Online and ArcGIS Enterprise item, this property will be to
   * routing service's default travel mode (see `defaultTravelMode` of [NetworkServiceDescription](https://developers.arcgis.com/javascript/latest/references/core/rest/support/NetworkServiceDescription/)).
   *
   * @see [Default travel modes](https://doc.arcgis.com/en/arcgis-online/reference/travel-modes.htm#GUID-96DF7F50-E0B2-4BF3-8271-EB515D3F0107)
   * @example
   * // Create a RouteLayer and assign to the DirectionsViewModel.
   * const layer = new RouteLayer();
   * map.add(layer);
   *
   * const apiKey = "<your api key>";
   * const directionsViewModel = new DirectionsViewModel({ apiKey, layer });
   * await directionsViewModel.load(); // wait for the view model to load the route service's "service description".
   *
   * // Print view model's selected travel mode. This will be equivalent to the routing service's default travel mode.
   * console.log(directionsViewModel.selectedTravelMode.name);
   *
   * // Assign the "Walking Time" travel mode.
   * directionsViewModel.selectedTravelMode = directionsViewModel.travelModes.find(({ name }) => name === "Walking Time");
   */
  get selectedTravelMode(): TravelMode | null | undefined;
  set selectedTravelMode(value: TravelModeProperties | null | undefined);
  /**
   * The Service Description object returned by the Route REST Endpoint. This object contains
   * three properties: `currentVersion`, `defaultTravelMode`, and `supportedTravelModes`.
   *
   * This information is useful when implementing complex logistics scenarios operating with
   * limitations or preferences on vehicle or stop properties, for example avoiding toll roads,
   * dealing with hazardous materials, working with stop service times, etc.
   */
  get serviceDescription(): NetworkServiceDescription | null | undefined;
  /**
   * The current state of the view model.
   *
   * @default "disabled"
   */
  get state(): State;
  /** The name of the network attribute to use for the drive time when computing directions. */
  get timeAttribute(): NetworkAttribute | null | undefined;
  /**
   * An array of available [travel modes](https://developers.arcgis.com/javascript/latest/references/core/rest/support/TravelMode/) from the associated
   * [RouteLayer](https://developers.arcgis.com/javascript/latest/references/core/widgets/Directions/DirectionsViewModel/#layer)'s routing service (see [RouteLayer.url](https://developers.arcgis.com/javascript/latest/references/core/layers/RouteLayer/#url)).
   */
  get travelModes(): TravelMode[];
  /** The view from which the widget will operate. */
  accessor view: MapViewOrSceneView | null | undefined;
  /**
   * Centers the map at the specified maneuver or stop.
   *
   * @param stopOrManeuver - The stop or maneuver where the map should be centered.
   */
  centerAt(stopOrManeuver: Graphic | Stop | (GeometryUnion | null | undefined)): void;
  /** Clears any highlighted route segments. */
  clearHighlights(): void;
  /**
   * Removes the route directions from the directions list, leaving the inputs untouched. The route and locations
   * persist on the map.
   */
  clearResults(): void;
  /**
   * Returns the cost attribute associated with the parsed name.
   *
   * @param attributeName - The attribute name specifying the cost attribute used as an impedance.
   * @returns The cost attribute associated with the passed name.
   *
   * Property | Type   | Description
   * ---------|--------|----------------
   * name     | string | Name of the impedance network attribute.
   * units    | string | Units of this network attribute.
   */
  getCostAttribute(attributeName: string): NetworkAttribute | null | undefined;
  /**
   * Computes a route and directions. If successful, results will be assigned to [lastRoute](https://developers.arcgis.com/javascript/latest/references/core/widgets/Directions/DirectionsViewModel/#lastRoute)
   * and returned in a resolving promise. If a view is assigned, it will zoom to the extent of the route.
   *
   * @returns When resolved, returns a [RouteLayerSolveResult](https://developers.arcgis.com/javascript/latest/references/core/layers/types/#RouteLayerSolveResult).
   */
  getDirections(): Promise<RouteLayerSolveResult>;
  /**
   * Highlights the specified network feature.
   *
   * @param networkFeature - The network feature to highlight.
   * @returns Resolves when the highlight has been completed.
   * @since 4.24
   */
  highlight(networkFeature: DirectionLine | DirectionPoint | PointBarrier | PolygonBarrier | PolylineBarrier | RouteInfo | Stop): Promise<void>;
  /**
   * This method should be called to load the view model's routing resources.
   *
   * > [!WARNING]
   * >
   * > This method downloads service metadata from the assigned routing service.
   * > Call this method before accessing properties on the view model or
   * > whenever the [layer](https://developers.arcgis.com/javascript/latest/references/core/widgets/Directions/DirectionsViewModel/#layer) changes.
   *
   * @returns When resolved, the view model has loaded the route service metadata necessary for routing.
   */
  load(): Promise<void>;
  /** Resets the state of the ViewModel, clearing all the input stops and results in the widget and in the map. */
  reset(): void;
  /**
   * Saves the RouteLayer associated with the view model. This method will update the portal-item associated with
   * layer.
   *
   * @returns When resolved, returns a [PortalItem](https://developers.arcgis.com/javascript/latest/references/core/portal/PortalItem/).
   * @since 4.24
   * @see [RouteLayer.save()](https://developers.arcgis.com/javascript/latest/references/core/layers/RouteLayer/#save)
   * @see [RouteLayer.saveAs()](https://developers.arcgis.com/javascript/latest/references/core/layers/RouteLayer/#saveAs)
   */
  save(): Promise<PortalItem>;
  /**
   * Saves the RouteLayer associated with the view model as a new portal item.
   *
   * @param portalItem - The new [portal item](https://developers.arcgis.com/javascript/latest/references/core/portal/PortalItem/) to which the layer will be saved.
   * @param options - Save options. Currently, there is only one property that can be set, which is `folder`.
   * @returns Saved portal item.
   * @since 4.24
   * @see [RouteLayer.save()](https://developers.arcgis.com/javascript/latest/references/core/layers/RouteLayer/#save)
   * @see [RouteLayer.saveAs()](https://developers.arcgis.com/javascript/latest/references/core/layers/RouteLayer/#saveAs)
   */
  saveAs(portalItem: PortalItem, options?: LayerSaveAsOptions): Promise<PortalItem>;
  /**
   * Starts an edit session.
   *
   * @internal
   */
  startEditing(): void;
  /**
   * Ends an edit session.
   *
   * @internal
   */
  stopEditing(): void;
  /** Zoom so that the full route is displayed within the current map extent. */
  zoomToRoute(): void;
}
declare const DirectionsViewModelSuperclass: typeof EventedAccessor & typeof GoTo