import type Collection from "../core/Collection.js";
import type Extent from "../geometry/Extent.js";
import type Layer from "./Layer.js";
import type RouteSymbols from "./support/RouteSymbols.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 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 { MultiOriginJSONMixin, MultiOriginJSONMixinProperties } from "../core/MultiOriginJSONSupport.js";
import type { RouteLayerSolveResult } from "./types.js";
import type { BlendLayer, BlendLayerProperties } from "./mixins/BlendLayer.js";
import type { OperationalLayer, OperationalLayerProperties } from "./mixins/OperationalLayer.js";
import type { PortalLayer, PortalLayerProperties } from "./mixins/PortalLayer.js";
import type { ScaleRangeLayer, ScaleRangeLayerProperties } from "./mixins/ScaleRangeLayer.js";
import type { SaveAsOptions } from "./mixins/properties/ILayerWithSave.js";
import type { RequestOptions } from "../request/types.js";
import type { RouteSymbolsProperties } from "./support/RouteSymbols.js";
import type { PointBarrierProperties } from "../rest/support/PointBarrier.js";
import type { ReadonlyArrayOrCollection } from "../core/Collection.js";
import type { PolygonBarrierProperties } from "../rest/support/PolygonBarrier.js";
import type { PolylineBarrierProperties } from "../rest/support/PolylineBarrier.js";
import type { StopProperties } from "../rest/support/Stop.js";
import type { LayerProperties } from "./Layer.js";

export interface RouteLayerProperties extends LayerProperties, MultiOriginJSONMixinProperties, PortalLayerProperties, OperationalLayerProperties, ScaleRangeLayerProperties, BlendLayerProperties, Partial<Pick<RouteLayer, "url">> {
  /**
   * The default symbol used for new stops and route results generated by [solve()](https://developers.arcgis.com/javascript/latest/api-reference/esri-layers-RouteLayer.html#solve).
   *
   * @since 4.24
   * @example
   * // When a route is solved, display the direction lines with a thick cyan line and hide both diection points and the
   * // overall route line.
   * const layer = new RouteLayer({
   *   defaultSymbols: {
   *    directionLines: {
   *      type: "simple-line",
   *      color: [105, 220, 255],
   *      width: 7,
   *      cap: "round",
   *      join: "round"
   *    },
   *    directionPoints: {
   *      type: "simple-marker",
   *      size: 0
   *    },
   *    routeInfo: {
   *      type: "simple-line",
   *      width: 0
   *    }
   *   }
   * });
   */
  defaultSymbols?: RouteSymbolsProperties;
  /**
   * A collection of [PointBarrier](https://developers.arcgis.com/javascript/latest/api-reference/esri-rest-support-PointBarrier.html) are used to prevent navigation through the street
   * network.
   */
  pointBarriers?: ReadonlyArrayOrCollection<PointBarrierProperties>;
  /**
   * A collection of [PolygonBarrier](https://developers.arcgis.com/javascript/latest/api-reference/esri-rest-support-PolygonBarrier.html) are used to prevent navigation through the
   * street network.
   */
  polygonBarriers?: ReadonlyArrayOrCollection<PolygonBarrierProperties>;
  /**
   * A collection of [PolylineBarrier](https://developers.arcgis.com/javascript/latest/api-reference/esri-rest-support-PolylineBarrier.html) are used to prevent navigation through the
   * street network.
   */
  polylineBarriers?: ReadonlyArrayOrCollection<PolylineBarrierProperties>;
  /**
   * A collection of [Stop](https://developers.arcgis.com/javascript/latest/api-reference/esri-rest-support-Stop.html)s define the start, end, waypoint, or break of the route.
   *
   * @example
   * // Define a route between Cancun Airport and Playa del Carmen with a break at Chichén Itzá.
   * const routeLayer = new RouteLayer({
   *   stops: [
   *     { locationType: "stop",  geometry: { x: -86.9074392, y: 21.0847238 } }, // Cancun Airport
   *     { locationType: "break", geometry: { x: -88.1331506, y: 20.6354437 } }, // Chichén Itzá
   *     { locationType: "stop",  geometry: { x: -87.1067159, y: 20.6538687 } }  // Playa del Carmen
   *   ]
   * });
   */
  stops?: ReadonlyArrayOrCollection<StopProperties>;
  /**
   * The title of the layer used to identify it in places such as the [LayerList](https://developers.arcgis.com/javascript/latest/api-reference/esri-widgets-LayerList.html)
   * and [Popup](https://developers.arcgis.com/javascript/latest/api-reference/esri-widgets-Popup.html) widgets and in the portal item created by {@link layers/RouteLayer#saveas}.
   *
   * The title will default to the name of the solved route or "Route" if unsolved.
   */
  title?: string | null;
}

/**
 * RouteLayer is a layer for visualizing and solving routes. A solved route includes turn-by-turn directions,
 * and can be stored and retrieved from ArcGIS Online or Enterprise, either as a portal item, or as part of a
 * webmap.
 *
 * A RouteLayer consists of two or more stops, and optionally, point, polygon, and polyline barriers. Results of a
 * solved route are accessible from the [directionLines](https://developers.arcgis.com/javascript/latest/api-reference/esri-layers-RouteLayer.html#directionLines), [directionPoints](https://developers.arcgis.com/javascript/latest/api-reference/esri-layers-RouteLayer.html#directionPoints), and
 * [routeInfo](https://developers.arcgis.com/javascript/latest/api-reference/esri-layers-RouteLayer.html#routeInfo) properties. Results include overall travel time, distance, and turn-by-turn directions.
 *
 * @since 4.23
 * @see [route](https://developers.arcgis.com/javascript/latest/api-reference/esri-rest-route.html)
 * @see [RouteParameters](https://developers.arcgis.com/javascript/latest/api-reference/esri-rest-support-RouteParameters.html)
 * @see [Directions](https://developers.arcgis.com/javascript/latest/api-reference/esri-widgets-Directions.html)
 * @see [Sample - Intro to RouteLayer](https://developers.arcgis.com/javascript/latest/sample-code/layers-routelayer/)
 * @example
 * // Routing with the RouteLayer's default route service requires an apikey.
 * const apiKey = "<your api key>";
 *
 * // A minimum of two stops is required for routing.
 * const stops = [
 *   new Stop({ geometry: { x: -117.1825, y: 34.054722 }}),
 *   new Stop({ geometry: { x: -116.545278, y: 33.830278 }})
 * ];
 *
 * // Create route layer and assign the stops. Only solved routelayers will be rendered.
 * const routeLayer = new RouteLayer({
 *   stops
 * });
 *
 * // Create a view and add the routelayer to the view's map.
 * const view = new MapView({
 *   container: "viewDiv",
 *   map: new Map({
 *     basemap: "dark-gray-vector",
 *     layers: [ routeLayer ]
 *   })
 * });
 *
 * // Wait for the view to load since we'll be zooming to the extent of the zoomed solution.
 * view.when().then(async () => {
 *   // Solve the route using routelayer stops and barries and additional properties from the parsed RouteParameters
 *   // object. Use the RouteParameters to provide the apiKey and other setting like directions language and travel
 *   // mode.
 *   const results = await routeLayer.solve({ apiKey });
 *
 *   // Use the returned result to update the RouteLayer. This method will overwrite the stops, barriers, directions and
 *   // routeInfo properties.
 *   routeLayer.update(results);
 *
 *   // Zoom to the extent of the solve route.
 *   view.goTo(routeLayer.routeInfo.geometry);
 * });
 */
export default class RouteLayer extends RouteLayerSuperclass {
  constructor(properties?: RouteLayerProperties);
  /**
   * The default symbol used for new stops and route results generated by [solve()](https://developers.arcgis.com/javascript/latest/api-reference/esri-layers-RouteLayer.html#solve).
   *
   * @since 4.24
   * @example
   * // When a route is solved, display the direction lines with a thick cyan line and hide both diection points and the
   * // overall route line.
   * const layer = new RouteLayer({
   *   defaultSymbols: {
   *    directionLines: {
   *      type: "simple-line",
   *      color: [105, 220, 255],
   *      width: 7,
   *      cap: "round",
   *      join: "round"
   *    },
   *    directionPoints: {
   *      type: "simple-marker",
   *      size: 0
   *    },
   *    routeInfo: {
   *      type: "simple-line",
   *      width: 0
   *    }
   *   }
   * });
   */
  get defaultSymbols(): RouteSymbols;
  set defaultSymbols(value: RouteSymbolsProperties);
  /**
   * A collection of [DirectionLine](https://developers.arcgis.com/javascript/latest/api-reference/esri-rest-support-DirectionLine.html) that represent the linear path between [directionPoints](https://developers.arcgis.com/javascript/latest/api-reference/esri-layers-RouteLayer.html#directionPoints) of the
   * solved route.
   */
  get directionLines(): Collection<DirectionLine> | null | undefined;
  /**
   * A collection of [DirectionPoint](https://developers.arcgis.com/javascript/latest/api-reference/esri-rest-support-DirectionPoint.html) that represent the turn-by-turn directions along
   * a solved route.
   */
  get directionPoints(): Collection<DirectionPoint> | null | undefined;
  /**
   * The full extent of the layer.
   *
   * @example
   * // Once the layer loads, set the view's extent to the layer's fullextent
   * layer.when(function(){
   *   view.extent = layer.fullExtent;
   * });
   */
  get fullExtent(): Extent;
  /**
   * A collection of [PointBarrier](https://developers.arcgis.com/javascript/latest/api-reference/esri-rest-support-PointBarrier.html) are used to prevent navigation through the street
   * network.
   */
  get pointBarriers(): Collection<PointBarrier>;
  set pointBarriers(value: ReadonlyArrayOrCollection<PointBarrierProperties>);
  /**
   * A collection of [PolygonBarrier](https://developers.arcgis.com/javascript/latest/api-reference/esri-rest-support-PolygonBarrier.html) are used to prevent navigation through the
   * street network.
   */
  get polygonBarriers(): Collection<PolygonBarrier>;
  set polygonBarriers(value: ReadonlyArrayOrCollection<PolygonBarrierProperties>);
  /**
   * A collection of [PolylineBarrier](https://developers.arcgis.com/javascript/latest/api-reference/esri-rest-support-PolylineBarrier.html) are used to prevent navigation through the
   * street network.
   */
  get polylineBarriers(): Collection<PolylineBarrier>;
  set polylineBarriers(value: ReadonlyArrayOrCollection<PolylineBarrierProperties>);
  /** This property contains the solved route's geometry and other route information like overall time and distance. */
  get routeInfo(): RouteInfo | null | undefined;
  /**
   * A collection of [Stop](https://developers.arcgis.com/javascript/latest/api-reference/esri-rest-support-Stop.html)s define the start, end, waypoint, or break of the route.
   *
   * @example
   * // Define a route between Cancun Airport and Playa del Carmen with a break at Chichén Itzá.
   * const routeLayer = new RouteLayer({
   *   stops: [
   *     { locationType: "stop",  geometry: { x: -86.9074392, y: 21.0847238 } }, // Cancun Airport
   *     { locationType: "break", geometry: { x: -88.1331506, y: 20.6354437 } }, // Chichén Itzá
   *     { locationType: "stop",  geometry: { x: -87.1067159, y: 20.6538687 } }  // Playa del Carmen
   *   ]
   * });
   */
  get stops(): Collection<Stop>;
  set stops(value: ReadonlyArrayOrCollection<StopProperties>);
  /**
   * The title of the layer used to identify it in places such as the [LayerList](https://developers.arcgis.com/javascript/latest/api-reference/esri-widgets-LayerList.html)
   * and [Popup](https://developers.arcgis.com/javascript/latest/api-reference/esri-widgets-Popup.html) widgets and in the portal item created by {@link layers/RouteLayer#saveas}.
   *
   * The title will default to the name of the solved route or "Route" if unsolved.
   */
  accessor title: string | null | undefined;
  /**
   * The layer type provides a convenient way to check the type of the layer
   * without the need to import specific layer modules.
   */
  get type(): "route";
  /**
   * The URL of the REST endpoint of the Route service.
   *
   * By default, the layer will use the global routing serice
   * (see [ConfigWithRouteServiceUrl](https://developers.arcgis.com/javascript/latest/api-reference/esri-config.html#ConfigWithRouteServiceUrl)).
   *
   * If connected to a [Portal](https://developers.arcgis.com/javascript/latest/api-reference/esri-portal-Portal.html) you can use the route service advertised on the
   * portal's [helper services](https://developers.arcgis.com/javascript/latest/api-reference/esri-portal-Portal.html#helperServices) as demonstrated below.
   *
   * @see [ConfigWithRouteServiceUrl](https://developers.arcgis.com/javascript/latest/api-reference/esri-config.html#ConfigWithRouteServiceUrl)
   * @see [Portal#helperServices](https://developers.arcgis.com/javascript/latest/api-reference/esri-portal-Portal.html#helperServices)
   * @example
   * // Solve routes using the route service advertised on the portal
   * const portal = Portal.getDefault();
   * await portal.load();
   * const routeLayer = new RouteLayer({
   *   url: portal.helperServices.route.url
   * });
   * @example
   * // Solve routes using a defined route service
   * const routeLayer = new RouteLayer({
   *   url: "https://route-api.arcgis.com/arcgis/rest/services/World/Route/NAServer/Route_World"
   * });
   */
  accessor url: string;
  /**
   * Update the currently assigned [portal item](https://developers.arcgis.com/javascript/latest/api-reference/esri-portal-PortalItem.html) using information in this RouteLayer.
   *
   * @returns Saved portal item.
   * @see [saveAs()](https://developers.arcgis.com/javascript/latest/api-reference/esri-layers-RouteLayer.html#saveAs)
   * @example
   * // Create a route layer from an existing route portal item
   * const routeLayer = await Layer.fromPortalItem({
   *   portalItem: {
   *     id: "3828dfec3a0749a1b1aff9e2fa53157c"
   *   }
   * });
   *
   * // Add the route layer to a map
   * map.add(routeLayer);
   *
   * // Wait for both the view and route layer to load
   * await view.whenLayerView(routeLayer);
   *
   * // Zoom to the extent of the route layer
   * await view.goTo(routeLayer.fullExtent);
   *
   * // Update the route portal item on mouse click
   * view.on("click", async (event) => {
   *   // Reset the route layer's stops with the mouse click location being a waypoint
   *   routeLayer.stops = [
   *     { geometry: { x: -86.9074392, y: 21.0847238 } }, // Cancun Airport
   *     { geometry: event.mapPoint },                    // Mouse click location
   *     { geometry: { x: -88.1331506, y: 20.6354437 } }  // Chichén Itzá
   *   ];
   *
   *   // Solve the route
   *   const result = await routeLayer.solve({ apiKey });
   *
   *   // Use the results of the solve to update the route layer
   *   routeLayer.update(result);
   *
   *   // Refresh the route portal-item using the route layer
   *   await routeLayer.save();
   * });
   */
  save(): Promise<PortalItem>;
  /**
   * Saves the route layer to a new [portal item](https://developers.arcgis.com/javascript/latest/api-reference/esri-portal-PortalItem.html).
   * If saving is completed successfully the new portal item will be assigned to the [portalItem](https://developers.arcgis.com/javascript/latest/api-reference/esri-layers-RouteLayer.html#portalItem) property.
   *
   * If you want to update an existing portal item without changing ownership please use [save()](https://developers.arcgis.com/javascript/latest/api-reference/esri-layers-RouteLayer.html#save).
   *
   * @param portalItem - The new [portal item](https://developers.arcgis.com/javascript/latest/api-reference/esri-portal-PortalItem.html) 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.
   * @see [save()](https://developers.arcgis.com/javascript/latest/api-reference/esri-layers-RouteLayer.html#save)
   * @example
   * // Create a route between Cancun Airport and Chichén Itzá
   * // Save the route to AGOL as a new route portal item
   *
   * const apiKey = "<your api key here>";
   *
   * const routeLayer = new RouteLayer({
   *   stops: [
   *     { geometry: { x: -86.9074392, y: 21.0847238 } }, // Cancun Airport
   *     { geometry: { x: -88.1331506, y: 20.6354437 } }  // Chichén Itzá
   *   ]
   * });
   *
   * const webMap = new WebMap({
   *   basemap: "dark-gray-vector",
   *   layers: [
   *     routeLayer
   *   ]
   * });
   *
   * const view = new MapView({
   *   container: "viewDiv",
   *   map: webMap
   * });
   * await view.when();
   *
   * const result = await routeLayer.solve({ apiKey });
   * routeLayer.update(result);
   *
   * const extent = routeLayer.routeInfo.geometry.extent.clone().expand(1.5);
   * await view.goTo(extent);
   *
   * await routeLayer.saveAs({
   *   title: "Route from Cancun Airport to Chichén Itzá"
   * });
   */
  saveAs(portalItem: PortalItem, options?: SaveAsOptions): Promise<PortalItem>;
  /**
   * This method will solve the route using the route service referenced by {@link layers/RouteLayer#routeServiceUrl}
   * and the network objects [pointBarriers](https://developers.arcgis.com/javascript/latest/api-reference/esri-layers-RouteLayer.html#pointBarriers), [polylineBarriers](https://developers.arcgis.com/javascript/latest/api-reference/esri-layers-RouteLayer.html#polylineBarriers),
   * [polygonBarriers](https://developers.arcgis.com/javascript/latest/api-reference/esri-layers-RouteLayer.html#polygonBarriers), and [stops](https://developers.arcgis.com/javascript/latest/api-reference/esri-layers-RouteLayer.html#stops).
   *
   * Pass a reference to a [RouteParameters](https://developers.arcgis.com/javascript/latest/api-reference/esri-rest-support-RouteParameters.html) to specify or override route settings
   * such as [RouteParameters#travelMode](https://developers.arcgis.com/javascript/latest/api-reference/esri-rest-support-RouteParameters.html#travelMode) or the stops used.
   * If a [global apiKey](https://developers.arcgis.com/javascript/latest/api-reference/esri-config.html#ConfigWithApiKey) is not defined, the
   * [RouteParameters#apiKey](https://developers.arcgis.com/javascript/latest/api-reference/esri-rest-support-RouteParameters.html#apiKey) property can be used.
   *
   * @param routeParameters - The following properties are preset and <b>cannot</b> be overridden:
   *
   * Property                        | Value
   * --------------------------------|----------------
   * directionsOutputType            | "featuresets"
   * ignoreInvalidLocations          | `true`
   * preserveObjectID                | `true`
   * returnBarriers                  | `true`
   * returnDirections                | `true`
   * returnPolygonBarriers           | `true`
   * returnPolylineBarriers          | `true`
   * returnRoutes                    | `true`
   * returnStops                     | `true`
   *
   * The following properties will also be set automatically, but <b>can</b> be overridden:
   *
   * | Property                        | Default Value                                 |
   * |---------------------------------|-----------------------------------------------|
   * | pointBarriers                   | Same as [pointBarriers](https://developers.arcgis.com/javascript/latest/api-reference/esri-layers-RouteLayer.html#pointBarriers)       |
   * | polylineBarriers                | Same as [polylineBarriers](https://developers.arcgis.com/javascript/latest/api-reference/esri-layers-RouteLayer.html#polylineBarriers) |
   * | polygonBarriers                 | Same as [polygonBarriers](https://developers.arcgis.com/javascript/latest/api-reference/esri-layers-RouteLayer.html#polygonBarriers)   |
   * | stops                           | Same as [stops](https://developers.arcgis.com/javascript/latest/api-reference/esri-layers-RouteLayer.html#stops)                       |
   * @param requestOptions - Additional [options](https://developers.arcgis.com/javascript/latest/api-reference/esri-request.html#request) to be used for the data request
   * (will override requestOptions defined during construction).
   * @returns When resolved, returns a [RouteLayerSolveResult](https://developers.arcgis.com/javascript/latest/api-reference/esri-layers-types.html#RouteLayerSolveResult).
   * @see [update()](https://developers.arcgis.com/javascript/latest/api-reference/esri-layers-RouteLayer.html#update)
   * @example
   * // Solve and display a route between Cancun Airport and Chichén Itzá.
   * const apiKey = "<your api key>"
   *
   * // Create a route consisting of two stops.
   * const routeLayer = new RouteLayer({
   *   stops: [
   *     { geometry: { x: -86.9074392, y: 21.0847238 } }, // Cancun Airport
   *     { geometry: { x: -88.1331506, y: 20.6354437 } }  // Chichén Itzá
   *   ]
   * });
   *
   * const map = new Map({
   *   basemap: "dark-gray-vector",
   *   layers: [routeLayer]
   * });
   *
   * const view = new MapView({
   *   container: "viewDiv",
   *   map
   * });
   * await view.when();
   *
   * // Solve the route and use the results to update the layer.
   * const result = await routeLayer.solve({ apiKey });
   * routeLayer.update(result);
   *
   * // Zoom to the extent of the solved route.
   * view.goTo(routeLayer.routeInfo.geometry);
   */
  solve(routeParameters?: RouteParameters, requestOptions?: RequestOptions): Promise<RouteLayerSolveResult>;
  /**
   * Updates the layer with the results from a solved route layer.
   *
   * @param routeLayerSolveResult - See the table below for details of each parameter that may be passed to this method.
   * @see [solve()](https://developers.arcgis.com/javascript/latest/api-reference/esri-layers-RouteLayer.html#solve)
   */
  update(routeLayerSolveResult: RouteLayerSolveResult): void;
}
declare const RouteLayerSuperclass: typeof Layer & typeof MultiOriginJSONMixin & typeof PortalLayer & typeof OperationalLayer & typeof ScaleRangeLayer & typeof BlendLayer