/*
All material copyright Esri, All Rights Reserved, unless otherwise specified.
See https://js.arcgis.com/5.0/esri/copyright.txt for details.
*/
import{isSome as e}from"../../../core/arrayUtils.js";import t from"../../../core/Error.js";import{EventEmitter as r}from"../../../core/Evented.js";import s from"../../../core/Logger.js";import{fromRect as o,create as i}from"../../../geometry/support/aaBoundingBox.js";import{create as n}from"../../../geometry/support/aaBoundingRect.js";import{getBoundsOptimizedGeometry as u}from"../featureConversionUtils.js";import{BoundsStore as a}from"./BoundsStore.js";import{cleanFromGeometryEngine as d}from"./geometryUtils.js";import{optimizedFeatureQueryEngineAdapter as h}from"./optimizedFeatureQueryEngineAdapter.js";const m=i();class f{constructor(e){this.geometryInfo=e,this._boundsStore=new a,this._featuresById=new Map,this._usedMemory=0,this.events=new r,this.featureAdapter=h}get usedMemory(){return this._usedMemory}get geometryType(){return this.geometryInfo.geometryType}get hasM(){return this.geometryInfo.hasM}get hasZ(){return this.geometryInfo.hasZ}get numFeatures(){return this._featuresById.size}get fullBounds(){return this._boundsStore.fullBounds}get storeStatistics(){let e=0;return this._featuresById.forEach(t=>{null!=t.geometry&&t.geometry.coords&&(e+=t.geometry.coords.length)}),{featureCount:this._featuresById.size,vertexCount:e/(this.hasZ?this.hasM?4:3:this.hasM?3:2)}}getFullExtent(e){if(null==this.fullBounds)return null;const[t,r,s,o]=this.fullBounds;return{xmin:t,ymin:r,xmax:s,ymax:o,spatialReference:d(e)}}add(e){this._add(e),this._emitChanged()}addMany(e){for(const t of e)this._add(t);this._emitChanged()}upsertMany(t){const r=t.map(e=>this._upsert(e));return this._emitChanged(),r.filter(e)}clear(){this._featuresById.clear(),this._boundsStore.clear(),this._emitChanged(),this._usedMemory=0}removeById(e){const t=this._featuresById.get(e);return t?(this._remove(t),this._emitChanged(),t):null}removeManyById(e){this._boundsStore.invalidateIndex();for(const t of e){const e=this._featuresById.get(t);e&&this._remove(e)}this._emitChanged()}forEachBounds(e,t){for(const r of e){const e=this._boundsStore.get(r.objectId);e&&t(o(m,e))}}getFeature(e){return this._featuresById.get(e)}has(e){return this._featuresById.has(e)}forEach(e){this._featuresById.forEach(t=>e(t))}forEachInBounds(e,t){this._boundsStore.forEachInBounds(e,e=>{t(this._featuresById.get(e))})}_emitChanged(){this.events.emit("changed",void 0)}_add(e){if(!e)return;const r=e.objectId;if(null==r)return void s.getLogger("esri.layers.graphics.data.FeatureStore").error(new t("featurestore:invalid-feature","feature id is missing",{feature:e}));const o=this._featuresById.get(r);let i;if(o?(e.displayId=o.displayId,i=this._boundsStore.get(r),this._boundsStore.delete(r),this._usedMemory-=this.estimateFeatureUsedMemory?.(o)??0):null!=this.onFeatureAdd&&this.onFeatureAdd(e),!e.geometry?.coords?.length)return this._boundsStore.set(r,null),void this._featuresById.set(r,e);i=u(null!=i?i:n(),e.geometry),null!=i&&this._boundsStore.set(r,i),this._featuresById.set(r,e),this._usedMemory+=this.estimateFeatureUsedMemory?.(e)??0}_upsert(e){const r=e?.objectId;if(null==r)return s.getLogger("esri.layers.graphics.data.FeatureStore").error(new t("featurestore:invalid-feature","feature id is missing",{feature:e})),null;const o=this._featuresById.get(r);if(!o)return this._add(e),e;this._usedMemory-=this.estimateFeatureUsedMemory?.(o)??0;const{geometry:i,attributes:a}=e;for(const t in a)o.attributes[t]=a[t];return i&&(o.geometry=i,this._boundsStore.set(r,u(n(),i)??null)),this._usedMemory+=this.estimateFeatureUsedMemory?.(o)??0,o}_remove(e){null!=this.onFeatureRemove&&this.onFeatureRemove(e);const t=e.objectId;return this._boundsStore.delete(t),this._featuresById.delete(t),this._usedMemory-=this.estimateFeatureUsedMemory?.(e)??0,e}}export{f as default};
