/* COPYRIGHT Esri - https://js.arcgis.com/5.1.2/LICENSE.txt */
import{LRUCache as e}from"../../../../core/LRUCache.js";import{fromValues as t,create as i,intersects as s}from"../../../../geometry/support/aaBoundingRect.js";import{tileSizeInPixels as l}from"./constants.js";import r from"../../tiling/TileCoverage.js";import n from"../../tiling/TileKey.js";const o=1e-6;class a{constructor(t,i){this._tiles=new Map,this._tileCache=new e(40,e=>e.dispose()),this._viewSize=[0,0],this._visibleTiles=new Map,this._previousLevel=-1,this._currentLevel=-1,this.acquireTile=t.acquireTile,this.releaseTile=t.releaseTile,this.tileInfoView=t.tileInfoView,this._container=i}destroy(){for(const e of this._tiles.values())e.dispose();this._tiles=null,this._tileCache.clear(),this._tileCache=null}update(e){this._updateCacheSize(e);const t=this.tileInfoView,i=t.getTileCoverage(e.state,0,!0,"smallest");if(!i)return!0;const{spans:s,lodInfo:l}=i,{level:o}=l,a=this._tiles;this._currentLevel=o;const c=new Set,h=new Set;for(const{row:r,colFrom:f,colTo:u}of s)for(let e=f;e<=u;e++){const t=n.getId(o,r,l.normalizeCol(e),l.getWorldForColumn(e)),i=this._getOrAcquireTile(t);c.add(t),i.processed()?this._addToContainer(i):h.add(new n(t))}for(const[r,n]of a)n.isCoverage=c.has(r);for(const r of h)this._findPlaceholdersForMissingTiles(r,c);let d=!1;for(const[r,n]of a)n.neededForCoverage=c.has(r),n.neededForCoverage||!n.isHoldingForFade&&n.fader.isFinished()||!t.intersects(i,n.key)||c.add(r),n.isFading&&(n.fader.value()<1&&null!=n.parentTile&&n.parentTile.hasData()&&c.add(n.parentTile.id),d=!0);for(const r of this._tiles.keys())c.has(r)||this._releaseTile(r);return r.pool.release(i),this._previousLevel=o,!d}clear(){this._tiles.clear(),this._tileCache.clear(),this._visibleTiles.clear()}clearCache(){this._tileCache.clear()}getIntersectingTiles(e,l,r,n,o){const a=[0,0],c=[0,0];n.toMap(a,e-r,l+r),n.toMap(c,e+r,l-r);const h=Math.min(a[0],c[0]),d=Math.min(a[1],c[1]),f=Math.max(a[0],c[0]),u=Math.max(a[1],c[1]),_=t(h,d,f,u),p=i(),T=[],v=new Set;for(const t of this._visibleTiles.values())this.tileInfoView.getTileBounds(p,t.key),s(_,p)&&(T.push(t),v.add(t.id));if(null!=o)for(const t of o){const e=t.tileKey.id;if(v.has(e))continue;const i=this._visibleTiles.get(e);null!=i&&(T.push(i),v.add(e))}return T}isFading(){for(const e of this._visibleTiles.values())if(e.isFading)return!0;return!1}_findPlaceholdersForMissingTiles(e,t){let i=0;for(const s of this._tiles.values())if(i+=this._addPlaceholderChild(s,e,t),Math.abs(1-i)<o)return null;return this._addPlaceholderParent(e.id,t)}_addPlaceholderChild(e,t,i){if(e.key.level<=t.level||!e.hasData())return 0;if(h(t,e.key)){this._addToContainer(e),i.add(e.id);return 1/(1<<2*(e.key.level-t.level))}return 0}_addPlaceholderParent(e,t){const i=this._tiles;let s=e;for(;;){if(s=c(s),!s||t.has(s))return null;const e=i.get(s);if(e?.hasData())return this._addToContainer(e),t.add(e.id),s}}_getOrAcquireTile(e){let t=this._tiles.get(e);return t||(t=this._tileCache.pop(e),t||(t=this._applyPlaceholderOpacity(this.acquireTile(new n(e)))),this._tiles.set(e,t),t)}_applyPlaceholderOpacity(e){const t=this._tiles;let i=e.id;for(;i&&(i=c(i),i);){const s=t.get(i);if(s?.hasData())return e.fader?.setStartOpacity(s.fader?.value()??1),e}const s=this._currentLevel<this._previousLevel?1:0;return e.fader?.setStartOpacity(s),e}_releaseTile(e){const t=this._tiles.get(e);this.releaseTile(t),this._removeFromContainer(t),this._tiles.delete(e),t.hasData()?this._tileCache.put(e,t,1):t.dispose()}_addToContainer(e){let t;const i=[],s=this._container;if(s.contains(e))return;const l=this._visibleTiles;for(const r of l.values())this._canConnectDirectly(e,r)&&i.push(r),null==t&&this._canConnectDirectly(r,e)&&(t=r);if(null!=t){for(const s of i)t.childrenTiles.delete(s),e.childrenTiles.add(s),s.parentTile=e;t.childrenTiles.add(e),e.parentTile=t,e.fader.setStartOpacity(t.fader?.value()??1)}else{e.fader.reset();for(const t of i)e.childrenTiles.add(t),t.parentTile=e}l.set(e.id,e),s.addChild(e)}_removeFromContainer(e){if(this._visibleTiles.delete(e.id),this._container.removeChild(e),null!=e.parentTile){e.parentTile.childrenTiles.delete(e);for(const t of e.childrenTiles)e.parentTile.childrenTiles.add(t)}for(const t of e.childrenTiles)t.parentTile=e.parentTile;e.parentTile=null,e.childrenTiles.clear()}_canConnectDirectly(e,t){const i=e.key;let{level:s,row:l,col:r,world:n}=t.key;const o=this._visibleTiles;for(;s>0;){if(s--,l>>=1,r>>=1,i.level===s&&i.row===l&&i.col===r&&i.world===n)return!0;if(o.has(`${s}/${l}/${r}/${n}`))return!1}return!1}_updateCacheSize(e){const t=e.state.size;if(t[0]===this._viewSize[0]&&t[1]===this._viewSize[1])return;const i=Math.ceil(t[0]/l)+1,s=Math.ceil(t[1]/l)+1;this._viewSize[0]=t[0],this._viewSize[1]=t[1],this._tileCache.maxSize=5*i*s}}function c(e){const[t,i,s,l]=e.split("/"),r=parseInt(t,10);return 0===r?null:`${r-1}/${parseInt(i,10)>>1}/${parseInt(s,10)>>1}/${parseInt(l,10)}`}function h(e,t){const i=t.level-e.level;return e.row===t.row>>i&&e.col===t.col>>i&&e.world===t.world}export{a as TileManager};
