import{ERROR_THRESHOLD}from"./common.js";import DataTile,{asArrayLike,asImageLike,toArray}from"../DataTile.js";import EventType from"../events/EventType.js";import TileState from"../TileState.js";import Triangulation from"./Triangulation.js";import{calculateSourceExtentResolution,canvasPool,render as renderReprojected}from"../reproj.js";import{clamp}from"../math.js";import{createCanvasContext2D,releaseCanvas}from"../dom.js";import{getArea,getIntersection}from"../extent.js";import{listen,unlistenByKey}from"../events.js";class ReprojDataTile extends DataTile{constructor(t){super({tileCoord:t.tileCoord,loader:()=>Promise.resolve(new Uint8Array(4)),interpolate:t.interpolate,transition:t.transition}),this.pixelRatio_=t.pixelRatio,this.gutter_=t.gutter,this.reprojData_=null,this.reprojError_=null,this.reprojSize_=void 0,this.sourceTileGrid_=t.sourceTileGrid,this.targetTileGrid_=t.targetTileGrid,this.wrappedTileCoord_=t.wrappedTileCoord||t.tileCoord,this.sourceTiles_=[],this.sourcesListenerKeys_=null,this.sourceZ_=0;var e=this.targetTileGrid_.getTileCoordExtent(this.wrappedTileCoord_),i=this.targetTileGrid_.getExtent();let r=this.sourceTileGrid_.getExtent();i=i?getIntersection(e,i):e;if(0===getArea(i))this.state=TileState.EMPTY;else{const h=t.sourceProj;var e=h.getExtent(),e=(e&&(r=r?getIntersection(r,e):e),this.targetTileGrid_.getResolution(this.wrappedTileCoord_[0])),s=t.targetProj,a=calculateSourceExtentResolution(h,s,i,e);if(!isFinite(a)||a<=0)this.state=TileState.EMPTY;else{var o=void 0!==t.errorThreshold?t.errorThreshold:ERROR_THRESHOLD;if(this.triangulation_=new Triangulation(h,s,i,r,a*o,e),0===this.triangulation_.getTriangles().length)this.state=TileState.EMPTY;else{this.sourceZ_=this.sourceTileGrid_.getZForResolution(a);let e=this.triangulation_.calculateSourceExtent();if(r&&(h.canWrapX()?(e[1]=clamp(e[1],r[1],r[3]),e[3]=clamp(e[3],r[1],r[3])):e=getIntersection(e,r)),getArea(e)){var l=this.sourceTileGrid_.getTileRangeForExtentAndZ(e,this.sourceZ_);const c=t.getTileFunction;for(let t=l.minX;t<=l.maxX;t++)for(let e=l.minY;e<=l.maxY;e++){var n=c(this.sourceZ_,t,e,this.pixelRatio_);n&&this.sourceTiles_.push(n)}0===this.sourceTiles_.length&&(this.state=TileState.EMPTY)}else this.state=TileState.EMPTY}}}}getSize(){return this.reprojSize_}getData(){return this.reprojData_}getError(){return this.reprojError_}reproject_(){const T=[];if(this.sourceTiles_.forEach(t=>{if(t&&t.getState()===TileState.LOADED){var s=t.getSize(),i=this.gutter_;let e;var a=asArrayLike(t.getData()),o=(e=a||toArray(asImageLike(t.getData())),[s[0]+2*i,s[1]+2*i]),a=e instanceof Float32Array,s=o[0]*o[1];const u=a?Float32Array:Uint8Array;var l=new u(e.buffer),n=u.BYTES_PER_ELEMENT,i=n*l.length/s,h=l.byteLength/o[1],a=Math.floor(h/n/o[0]),s=s*a;let r=l;if(l.length!==s){r=new u(s);let t=0,i=0;var c=o[0]*a;for(let e=0;e<o[1];++e){for(let e=0;e<c;++e)r[t++]=l[i+e];i+=h/n}}T.push({extent:this.sourceTileGrid_.getTileCoordExtent(t.tileCoord),data:new Uint8Array(r.buffer),dataType:u,bytesPerPixel:i,pixelSize:o})}}),(this.sourceTiles_.length=0)===T.length)this.state=TileState.ERROR;else{var t=this.wrappedTileCoord_[0],i=this.targetTileGrid_.getTileSize(t),a="number"==typeof i?i:i[0],o="number"==typeof i?i:i[1],l=this.targetTileGrid_.getResolution(t),n=this.sourceTileGrid_.getResolution(this.sourceZ_),h=this.targetTileGrid_.getTileCoordExtent(this.wrappedTileCoord_);let e,s;var c=T[0].bytesPerPixel;for(let r=Math.ceil(c/3)-1;0<=r;--r){const m=[];for(let e=0,t=T.length;e<t;++e){var u=T[e],g=u.data,p=u.pixelSize,d=p[0],p=p[1];const R=createCanvasContext2D(d,p,canvasPool);d=R.createImageData(d,p);const x=d.data;let i=3*r;for(let e=0,t=x.length;e<t;e+=4)x[e]=g[i],x[e+1]=g[i+1],x[e+2]=g[i+2],x[e+3]=255,i+=c;R.putImageData(d,0,0),m.push({extent:u.extent,image:R.canvas})}const S=renderReprojected(a,o,this.pixelRatio_,n,this.sourceTileGrid_.getExtent(),l,h,this.triangulation_,m,this.gutter_,!1,!1);for(let e=0,t=m.length;e<t;++e){const y=m[e].image;var _=y.getContext("2d");releaseCanvas(_),canvasPool.push(_.canvas)}const v=S.getContext("2d");var E=v.getImageData(0,0,S.width,S.height),f=(releaseCanvas(v),canvasPool.push(S),e||(s=new Uint8Array(c*E.width*E.height),e=new T[0].dataType(s.buffer)),E.data);let i=3*r;for(let e=0,t=f.length;e<t;e+=4)255===f[e+3]?(s[i]=f[e],s[i+1]=f[e+1],s[i+2]=f[e+2]):(s[i]=0,s[i+1]=0,s[i+2]=0),i+=c}this.reprojData_=e,this.reprojSize_=[Math.round(a*this.pixelRatio_),Math.round(o*this.pixelRatio_)],this.state=TileState.LOADED}this.changed()}load(){if(this.state===TileState.IDLE||this.state===TileState.ERROR){this.state=TileState.LOADING,this.changed();let r=0;this.sourcesListenerKeys_=[],this.sourceTiles_.forEach(t=>{var e=t.getState();if(e===TileState.IDLE||e===TileState.LOADING){r++;const i=listen(t,EventType.CHANGE,function(){var e=t.getState();e!=TileState.LOADED&&e!=TileState.ERROR&&e!=TileState.EMPTY||(unlistenByKey(i),0===--r&&(this.unlistenSources_(),this.reproject_()))},this);this.sourcesListenerKeys_.push(i)}}),0===r?setTimeout(this.reproject_.bind(this),0):this.sourceTiles_.forEach(function(e){e.getState()==TileState.IDLE&&e.load()})}}unlistenSources_(){this.sourcesListenerKeys_.forEach(unlistenByKey),this.sourcesListenerKeys_=null}}export default ReprojDataTile;