/*
All material copyright Esri, All Rights Reserved, unless otherwise specified.
See https://js.arcgis.com/5.0/esri/copyright.txt for details.
*/
import{removeMaybe as e}from"./maybe.js";import{createResolver as s,onAbort as t,onAbortOrThrow as r,isPromiseLike as i,createAbortError as h}from"./promiseUtils.js";import c from"./Queue.js";import n from"./ReactiveMap.js";import{schedule as o}from"./scheduling.js";import{signal as l}from"./signal.js";class u{constructor(e){this._schedule=null,this._deferreds=new n,this._controllers=new n,this._processingItems=new n,this._pausedSignal=l(!1),this.process=e.process,this.concurrency=e.concurrency,this.sharedConcurrency=e.sharedConcurrency??p,this._queue=new c(e.peeker)}destroy(){this.clear(),this._schedule=e(this._schedule)}get updating(){return this.running}get length(){return this._processingItems.size+this._queue.length}get running(){return!this._pausedSignal.value&&this._queue.length>0&&!this.full}get full(){return this._processingItems.size>=this.concurrency||this.sharedConcurrency.full}abort(e){const s=this._controllers.get(e);s?.abort()}clear(){this._queue.clear();const e=Array.from(this._controllers.values());this._controllers.clear(),e.forEach(e=>e.abort()),this.sharedConcurrency.current.value-=this._processingItems.size,this._processingItems.clear(),this._cancelNext()}forEach(e){this._deferreds.forEach((s,t)=>e(t))}_get(e){const s=this._deferreds.get(e);return s?.promise}pause(){this._pausedSignal.value||(this._pausedSignal.value=!0,this._cancelNext())}push(e,i){const c=this._get(e);if(c)return c;const n=new AbortController,o=s(),l=i?t(i,()=>n.abort()):null,u=()=>{const s=this._processingItems.get(e);s&&s.controller.abort(),a(),o.reject(h())},_=r(n.signal,u),a=()=>{_.remove(),l?.remove(),this._removeItem(e),this._queue.remove(e),this._scheduleNext()};return this._deferreds.set(e,o),this._controllers.set(e,n),o.promise.then(a,a),this._queue.push(e),this._scheduleNext(),o.promise}last(){return this._queue.last()}reset(){const e=Array.from(this._processingItems.values());this.sharedConcurrency.current.value-=this._processingItems.size,this._processingItems.clear();for(const s of e)this._queue.push(s.item),s.controller.abort();this._scheduleNext()}resume(){this._pausedSignal.value&&(this._pausedSignal.value=!1,this._scheduleNext())}takeAll(){const e=[];for(;this._queue.length;)e.push(this._queue.pop());return this.clear(),e}_removeItem(e){this._deferreds.delete(e),this._controllers.delete(e),this._processingItems.has(e)&&(this._processingItems.delete(e),this.sharedConcurrency.current.value-=1)}_scheduleNext(){this._pausedSignal.value||this._schedule||(this._schedule=o(()=>{this._schedule=null,this._next()}))}_next(){for(;this._queue.length>0&&this._processingItems.size<this.concurrency&&!this.sharedConcurrency.full;)this._process(this._queue.pop())}_cancelNext(){this._schedule&&(this._schedule.remove(),this._schedule=null)}_processResult(e,s){this._canProcessFulfillment(e)&&(this._scheduleNext(),this._deferreds.get(e.item).resolve(s))}_processError(e,s){this._canProcessFulfillment(e)&&(this._scheduleNext(),this._deferreds.get(e.item).reject(s))}_canProcessFulfillment(e){return!!this._deferreds.get(e.item)&&this._processingItems.get(e.item)===e}_process(e){if(null==e)return;let s;const t=new AbortController,r=new _(e,t);this._processingItems.set(e,r),this.sharedConcurrency.current.value+=1;try{s=this.process(e,t.signal)}catch(h){this._processError(r,h)}i(s)?(r.promise=s,s.then(e=>this._processResult(r,e),e=>this._processError(r,e))):this._processResult(r,s)}}class _{constructor(e,s){this.item=e,this.controller=s,this.promise=null}}class a{constructor(e){this.limit=e,this.current=l(0)}get full(){return this.current.value>=this.limit}}const p=new a(1/0);export{u as QueueProcessor,a as SharedConcurrency};
