/*
All material copyright Esri, All Rights Reserved, unless otherwise specified.
See https://js.arcgis.com/5.0/esri/copyright.txt for details.
*/
import t from"../../../../../core/Error.js";import e from"../../../../../core/Logger.js";import{create as i}from"../../../../../geometry/support/aaBoundingRect.js";import{getBoundsXY as r}from"../../../../../geometry/support/boundsUtils.js";import{normalizeQueryLike as s}from"../../../../../layers/graphics/data/queryUtils.js";import{getSpatialQueryOperator as o}from"../../../../../layers/graphics/data/spatialQuerySupport.js";import{getTimeOperator as a}from"../../../../../layers/graphics/data/timeSupport.js";import l from"../../../../../rest/support/Query.js";import{FeatureStoreQueryAdapter as h}from"../FeatureStoreQueryAdapter.js";import{createWhereClause as n}from"./whereUtils.js";const m=1,d=2;class p{constructor(t){this._geometryBounds=i(),this._idToVisibility=new Map,this._serviceInfo=t}static async create(t){const e=new p(t);return await e.update(t.filterJSON,t.spatialReference),e}get hash(){return this._hash}check(t,e){return this._applyFilter(t,e)}invalidate(){this._idToVisibility.forEach((t,e)=>{this._idToVisibility.set(e,0)})}setKnownIds(t){for(const e of t)this._idToVisibility.set(e,m)}setTrue(t){const e=[],i=[],r=new Set(t);return this._idToVisibility.forEach((t,s)=>{const o=!!(this._idToVisibility.get(s)&m),a=r.has(s);!o&&a?e.push(s):o&&!a&&i.push(s),this._idToVisibility.set(s,a?m|d:0)}),{show:e,hide:i}}createQuery(){const{geometry:t,spatialRel:e,where:i,timeExtent:r,objectIds:s}=this;return l.fromJSON({geometry:t,spatialRel:e,where:i,timeExtent:r,objectIds:s})}async update(t,e){this._hash=JSON.stringify(t);const i=await s(t,null,e);await Promise.all([this._setGeometryFilter(i),this._setIdFilter(i),this._setAttributeFilter(i),this._setTimeFilter(i)])}async _setAttributeFilter(t){if(!t?.where)return this._clause=null,void(this.where=null);this._clause=await n(t.where,this._serviceInfo.fieldsIndex),this.where=t.where}_setIdFilter(t){this._idsToShow=t?.objectIds&&new Set(t.objectIds),this._idsToHide=t?.hiddenIds&&new Set(t.hiddenIds),this.objectIds=t?.objectIds}async _setGeometryFilter(t){if(!t?.geometry)return this._spatialQueryOperator=null,this.geometry=null,void(this.spatialRel=null);const e=t.geometry,i=t.spatialRel??"esriSpatialRelIntersects",s=await o(i,e,this._serviceInfo.geometryType);r(this._geometryBounds,e),this._spatialQueryOperator=s,this.geometry=e,this.spatialRel=i}_setTimeFilter(i){if(this.timeExtent=this._timeOperator=null,i?.timeExtent){if(!this._serviceInfo.timeInfo){const r=new t("feature-layer-view:time-filter-not-available","Unable to apply time filter, as layer doesn't have time metadata.",i.timeExtent);return void e.getLogger("esri.views.2d.layers.features.controllers.FeatureFilter").error(r)}this.timeExtent=i.timeExtent,this._timeOperator=a(this._serviceInfo.timeInfo,i.timeExtent,h.Shared)}}_applyFilter(t,e){return this._filterByGeometry(t)&&this._filterById(t)&&this._filterByTime(t)&&this._filterByExpression(t,e)}_filterByExpression(t,e){return!this.where||this._clause(t,e)}_filterById(t){return(!this._idsToHide?.size||!this._idsToHide.has(t.getObjectId()))&&(!this._idsToShow?.size||this._idsToShow.has(t.getObjectId()))}_filterByGeometry(t){if(!this.geometry)return!0;const e=t.readGeometryWorldSpace();return!!e&&this._spatialQueryOperator(e)}_filterByTime(t){return null==this._timeOperator||this._timeOperator(t)}}export{p as default};
