/* COPYRIGHT Esri - https://js.arcgis.com/5.1.0/LICENSE.txt */
import t from"../../../core/CircularArray.js";import e from"../../../core/Error.js";import{clamp as s}from"../../../core/mathUtils.js";import{defaultStreamIdField as i,esriTimestamp as r,internalTimeReceivedField as o}from"../../support/streamLayerUtils.js";const d=1e3;class a{constructor(t,s,r,o,d=128){if(this._trackIdToObservations=new Map,this._idCounter=0,this._lastPurge=performance.now(),this._addOrUpdated=new Map,this._removed=[],this._maxAge=0,this._timeInfo=r,this._purgeOptions=o,this.store=t,"unique-id-composite"===s.type)throw new e("stream-layer","composite uniqueIds are not supported");this.idField=s.fieldName,this.purgeInterval=d,this._useGeneratedIds=this.idField===i}removeById(t){this._removed.push(t)}removeByTrackId(t){const e=this._trackIdToObservations.get(t);if(e)for(const s of e.entries)this._removed.push(s)}add(e){if(this._useGeneratedIds){const t=this._nextId();e.attributes[this.idField]=t,e.objectId=t}else e.objectId=e.attributes[this.idField];const i=e.objectId;if(this._addOrUpdated.set(i,e),this._maxAge=Math.max(this._maxAge,e.attributes[this._timeInfo.startTimeField]),!this._timeInfo.trackIdField)return null==this._trackIdLessObservations&&(this._trackIdLessObservations=new t(1e5)),void this._trackIdLessObservations.enqueue(i);const r=e.attributes[this._timeInfo.trackIdField];if(!this._trackIdToObservations.has(r)){const e=null!=this._purgeOptions?.maxObservations?this._purgeOptions.maxObservations:d,i=s(e,0,d);this._trackIdToObservations.set(r,new t(i))}const o=this._trackIdToObservations.get(r),a=o?.enqueue(i);null!=a&&(this._addOrUpdated.has(a)?this._addOrUpdated.delete(a):this._removed.push(a))}checkForUpdates(){const t=this._getToAdd(),e=this._getToRemove(),s=performance.now(),i=s-this._lastPurge,d=Date.now();i>=this.purgeInterval&&(this._purge(s),this._lastPurge=s);const a=[];if(null!=e)for(const r of e){const t=this.store.removeById(r);null!=t&&a.push(t)}const n=[];if(null!=t){const i=new Set(e??[]);for(const e of t)i.has(e.objectId)||(e.attributes[r]=s,e.attributes[o]=d,this.store.add(e),n.push(e))}return!(!n.length&&!a?.length)&&(this.store.update(n,a),!0)}_getToAdd(){if(!this._addOrUpdated.size)return null;const t=new Array(this._addOrUpdated.size);let e=0;return this._addOrUpdated.forEach(s=>t[e++]=s),this._addOrUpdated.clear(),t}_getToRemove(){const t=this._removed;return this._removed.length?(this._removed=[],t):null}_nextId(){const t=this._idCounter;return this._idCounter=(this._idCounter+1)%4294967294+1,t}_purge(t){const e=this._purgeOptions;null!=e&&(this._purgeSomeByDisplayCount(e),this._purgeByAge(e),this._purgeByAgeReceived(t,e),this._purgeTracks())}_purgeSomeByDisplayCount(t){if(!t.displayCount)return;let e=this.store.size;if(e>t.displayCount){if(this._timeInfo.trackIdField)for(const s of this._trackIdToObservations.values())if(e>t.displayCount&&s.size){const t=s.dequeue();this._removed.push(t),e--}if(null!=this._trackIdLessObservations){let s=e-t.displayCount;for(;s-- >0;){const t=this._trackIdLessObservations.dequeue();null!=t&&this._removed.push(t)}}}}_purgeByAge(t){const e=this._timeInfo?.startTimeField;if(!t.age||!e)return;const s=60*t.age*1e3,i=this._maxAge-s;this.store.forEach(t=>{t.attributes[e]<i&&this._removed.push(t.objectId)})}_purgeByAgeReceived(t,e){if(!e.ageReceived)return;const s=t-60*e.ageReceived*1e3;this.store.forEach(t=>{t.attributes[r]<s&&this._removed.push(t.objectId)})}_purgeTracks(){this._trackIdToObservations.forEach((t,e)=>{0===t.size&&this._trackIdToObservations.delete(e)})}}export{a as StreamFeatureManager};
