/**
 * This module is a utility framework that simplifies the use of
 * [Web Workers](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Using_web_workers) in the
 * ArcGIS Maps SDK for JavaScript.
 *
 * The workers framework takes advantage of multi-core CPUs to perform computationally expensive tasks in
 * a background thread without interfering with the user interface. This framework loads a script
 * and provides a calling function in the main thread using the [Connection class](https://developers.arcgis.com/javascript/latest/references/core/core/workers/Connection/).
 * The Connection can then be used to offload jobs asynchronously from the main thread to workers.
 * The workers framework returns a Promise once the job is completed.
 *
 * > [!WARNING]
 * >
 * > **Known Limitations**
 * >
 * > Workers do not have access to document, window and parent objects, and cannot directly affect the parent page; this includes
 * > DOM manipulation.
 * >
 * > The [esriRequest](https://developers.arcgis.com/javascript/latest/references/core/request/) module can be used within worker script with the following exceptions:
 * >   - [esriRequest.options.body](https://developers.arcgis.com/javascript/latest/references/core/request/types/#RequestOptions) `FormData` value is not supported.
 * >   - [esriRequest.options.responseType](https://developers.arcgis.com/javascript/latest/references/core/request/types/#RequestOptions) supported values are: `array-buffer`, `blob`, `json`, `native`, `text`
 * >   - [esriRequest.getHeader](https://developers.arcgis.com/javascript/latest/references/core/request/types/#GetHeader) is not supported.
 *
 * @since 4.2
 * @see [ES modules custom workers sample](https://github.com/Esri/jsapi-resources/tree/main/templates/geometry-operator-worker)
 */
import type Connection from "./workers/Connection.js";
import type { AbortOptions } from "./promiseUtils.js";

/**
 * Indicates how to load the module. See the table below for a list of possible values.
 *
 * Possible Value | Description
 * ---------------|------------
 * distributed | The module is loaded in each available worker. Each call to [Connection.invoke()](https://developers.arcgis.com/javascript/latest/references/core/core/workers/Connection/#invoke) will be targeting an available worker. Use this strategy if the module doesn't maintain information between invocations (stateless).
 * dedicated | The module is loaded in one worker. Each call to [Connection.invoke()](https://developers.arcgis.com/javascript/latest/references/core/core/workers/Connection/#invoke) will be targeting a same worker. Use this strategy if the module maintains information from previous invocations or communication between main and worker threads needs to be stateful.
 * local | The module is loaded in the main thread. Use this strategy when using the worker framework API while disabling the use of workers.
 */
export type OpenStrategy = "distributed" | "dedicated" | "local";

export interface OpenOptions extends AbortOptions {
  /** The objects defining the API accessible from the module. */
  client?: any;
  /**
   * Indicates how to load the module. See the table below for a list of possible values.
   *
   * @default distributed
   */
  strategy?: OpenStrategy;
}

/**
 * Opens a connection to workers and loads a script with the workers framework.
 *
 * @param modulePath - A fully qualified URL to a script to execute with the workers framework.
 * @param options - Worker options. See properties below for object specifications.
 * @returns Resolves to an instance of [Connection](https://developers.arcgis.com/javascript/latest/references/core/core/workers/Connection/).
 * @see [Connection](https://developers.arcgis.com/javascript/latest/references/core/core/workers/Connection/)
 * @example
 * // Set the path for the worker's AMD loader configuration
 * // to a folder called workersFolder.
 * esriConfig.workers.loaderConfig = {
 *  paths: {
 *    myWorkers: new URL("./workersFolder", document.baseURI).href
 *  }
 * };
 *
 * // load myWorkers/Calculator.js in the workers framework
 * // and invoke its "getMaxNumber" method
 * workers.open("myWorkers/Calculator")
 *   .then((connection) => {
 *     return connection.invoke("getMaxNumber", [0, 1, 2, 3, 4]);
 *   })
 *   .then((result) => {
 *     console.log(result);
 *   });
 *
 * //*********************************************************
 * // module: workerFolder/Calculator.js
 * //*********************************************************
 * define([], () => {
 *   return {
 *     // this function can be invoked from the main thread
 *     getMaxNumber: function (number) {
 *       return Math.max.apply(null, numbers);
 *     }
 *   };
 * });
 * @example
 * // Load workerScripts/TimeOfTheDay.js in the workers framework
 * // We define an API accessible from the module
 * workers.open(new URL("./workerScripts/TimeOfDay.js", document.baseURI).href, {
 *   client: {
 *     getCurrentTime: function() {
 *       return Date.now();
 *     }
 *   }
 * })
 *   .then((connection) => {
 *     return connection.invoke("timeOfTheDay");
 *   })
 *   .then((result) => {
 *     console.log(result);
 *   });
 *
 * //*********************************************************
 * // module: workerScripts/TimeOfTheDay.js
 * //*********************************************************
 *
 * define([], () => {
 *
 *   return {
 *     timeOfTheDay: function(noArgs, remoteClient) {
 *       // call back the main thread to get the current time over there.
 *       return remoteClient.invoke("getCurrentTime")
 *         .then((time) => {
 *           return "The time is " + time;
 *         });
 *     }
 *   };
 * });
 */
export function open(modulePath: string, options?: OpenOptions): Promise<Connection>;