/**
 * Creates a worker.
 *
 * @example
 * ```js
 * // When running in a web browser.
 * import createWorkerInBrowser from './createWorkerInBrowser.ts'
 *
 * // Create a worker.
 * const workerFn = createWorkerFn(
 * 	// Creates a worker in a given environment.
 * 	createWorkerInBrowser,
 *
 * 	// (optional) Filters `transferList` argument.
 * 	undefined,
 *
 * 	// Any "outside" dependencies that're referenced in the function (below).
 * 	[() => [outsideVar1, outsideVar2, func1, func2]],
 *
 * 	// Returns a function in the worker that processes input data.
 * 	(respond) => {
 *  	return (data) => {
 * 			// Process the data (perform some kind of calculation).
 * 			const result = processData(data)
 * 			// Post the result of the calculation back to the main thread.
 * 			respond(result) // (optional) add `transferList` argument.
 * 		}
 *  },
 *
 * 	// A function in the main thread that will be called every time
 * 	// when the worker has finished processing the data
 * 	// (or threw an error while doing that).
 * 	(error, result) => {
 * 		if (error) {
 * 			workerFn.stop()
 * 			throw error
 * 		}
 * 		// If no more data will be passed to the worker, it should be terminated.
 * 		workerFn.stop()
 * 		console.log(result)
 * 	}
 * )
 *
 * workerFn.start()
 *
 * // Post a message with some data to the worker
 * // so that it starts processing the data
 * // and later posts a message back to the main thread
 * // with the result of the calculation.
 * workerFn.input(inputData) // (optional) add `transferList` argument.
 * ```
 *
 * @param {function} createWorkerInEnvironment — Creates a worker in a given environment. The worker must call globally-available `onMessage(data)` function every time it receives a message, and it must define a `var postMessage = (data) => void` function that posts a message to the parent (main) thread.
 * @param {function} createInputHandler — A "creator" that creates a function that will be called with message data every time a message is sent to this worker. The "creator" function receives a single argument — a function that posts data back to the main thread, with two arguments: `outputData` and (optional) `transferList`.
 * @param {function} onError — This function will be called every time when there was an error while processing an incoming message. It would be logical to call `worker.terminate()` inside this function.
 * @param {function} onOutput — This function will be called every time when done processing an incoming message.
 * @param {function} getFromCache — Could be used to add caching. Has no arguments. Returns the cached value.
 * @param {function} setInCache — Could be used to add caching. Receives the value to cache as an argument. Doesn't return anything.
 * @returns {Worker} — An object with methods: `start(getDependenciesFunctionOrArrayOfGetDependenciesFunctions)`, `stop()`, `input(data, [transferList])`. Calling `stop()` requests termination of the worker. Calling `stop()` multiple times is safe and will not throw any errors.
 */
export default function createWorker<Input, Output>(createWorkerInEnvironment: CreateWorkerInEnvironment, createInputHandler: CreateInputHandler<Input, Output>, onError: (error: unknown) => void, onOutput: (inputSentTimestampAndInputReceivedTimestampAndOutputSentTimestampAndOutput: InputSentTimestampAndInputReceivedTimestampAndOutputSentTimestampAndOutput<Output>) => void, getFromCache: () => CacheValue | undefined, setInCache: (value: CacheValue) => void): UniversalWorker;
type CodeAndVars = [string, Record<string, unknown>];
interface CacheValue {
    _?: CodeAndVars;
    other?: any;
}
export type InputSentTimestampAndInputReceivedTimestampAndOutputSentTimestampAndOutput<Output> = [number, number, number, Output];
export type SendOutput<Output> = (inputSentTimestampAndInputReceivedTimestampAndOutputSentTimestampAndOutput: InputSentTimestampAndInputReceivedTimestampAndOutputSentTimestampAndOutput<Output>, transferList?: Transferable[]) => void;
type CreateInputHandler<Input, Output> = (send: SendOutput<Output>) => (input: Input) => void;
export type GetDependencies = () => any[];
export interface EnvironmentWorker {
    ingest(data: any, transferList?: readonly Transferable[]): void;
    stop(): void;
}
export interface UniversalWorker {
    start(arrayOfGetDependenciesFunctions: GetDependencies[], dependenciesTransferList?: Transferable[]): void;
    stop(): void;
    ingest(data: unknown, transferList?: Transferable[]): void;
}
export type CreateWorkerInEnvironment = <Output>(javascriptCode: string, getFromCache: () => any | undefined, setInCache: (value: any) => void, onError: (error: unknown) => void, onOutput: (output: Output) => void) => EnvironmentWorker;
export {};
