import Event from"../events/Event.js";import EventType from"../events/EventType.js";import ImageState from"../ImageState.js";import ImageWrapper from"../Image.js";import ReprojImage from"../reproj/Image.js";import Source from"./Source.js";import{DECIMALS}from"./common.js";import{ceil}from"../math.js";import{containsExtent,equals,getCenter,getForViewAndSize,getHeight,getWidth}from"../extent.js";import{equivalent}from"../proj.js";import{fromResolutionLike}from"../resolution.js";import{linearFindNearest}from"../array.js";const ImageSourceEventType={IMAGELOADSTART:"imageloadstart",IMAGELOADEND:"imageloadend",IMAGELOADERROR:"imageloaderror"};class ImageSourceEvent extends Event{constructor(e,t){super(e),this.image=t}}class ImageSource extends Source{constructor(e){super({attributions:e.attributions,projection:e.projection,state:e.state,interpolate:void 0===e.interpolate||e.interpolate}),this.on,this.once,this.un,this.loader=e.loader||null,this.resolutions_=void 0!==e.resolutions?e.resolutions:null,this.reprojectedImage_=null,this.reprojectedRevision_=0,this.image=null,this.wantedExtent_,this.wantedResolution_,this.static_=!!e.loader&&0===e.loader.length,this.wantedProjection_=null}getResolutions(){return this.resolutions_}setResolutions(e){this.resolutions_=e}findNearestResolution(e){var t=this.getResolutions();return e=t?t[linearFindNearest(t,e,0)]:e}getImage(e,t,i,o){const n=this.getProjection();if(!n||!o||equivalent(n,o))return n&&(o=n),this.getImageInternal(e,t,i,o);if(this.reprojectedImage_){if(this.reprojectedRevision_==this.getRevision()&&equivalent(this.reprojectedImage_.getProjection(),o)&&this.reprojectedImage_.getResolution()==t&&equals(this.reprojectedImage_.getExtent(),e))return this.reprojectedImage_;this.reprojectedImage_.dispose(),this.reprojectedImage_=null}return this.reprojectedImage_=new ReprojImage(n,o,e,t,i,(e,t,i)=>this.getImageInternal(e,t,i,n),this.getInterpolate()),this.reprojectedRevision_=this.getRevision(),this.reprojectedImage_}getImageInternal(e,t,i,o){if(this.loader){e=getRequestExtent(e,t,i,1),t=this.findNearestResolution(t);if(this.image&&(this.static_||this.wantedProjection_===o&&(this.wantedExtent_&&containsExtent(this.wantedExtent_,e)||containsExtent(this.image.getExtent(),e))&&(this.wantedResolution_&&fromResolutionLike(this.wantedResolution_)===t||fromResolutionLike(this.image.getResolution())===t)))return this.image;this.wantedProjection_=o,this.wantedExtent_=e,this.wantedResolution_=t,this.image=new ImageWrapper(e,t,i,this.loader),this.image.addEventListener(EventType.CHANGE,this.handleImageChange.bind(this))}return this.image}handleImageChange(e){const t=e.target;let i;switch(t.getState()){case ImageState.LOADING:this.loading=!0,i=ImageSourceEventType.IMAGELOADSTART;break;case ImageState.LOADED:this.loading=!1,i=ImageSourceEventType.IMAGELOADEND;break;case ImageState.ERROR:this.loading=!1,i=ImageSourceEventType.IMAGELOADERROR;break;default:return}this.hasListener(i)&&this.dispatchEvent(new ImageSourceEvent(i,t))}}function defaultImageLoadFunction(e,t){e.getImage().src=t}function getRequestExtent(e,t,i,o){var t=t/i,i=getCenter(e),n=ceil(getWidth(e)/t,DECIMALS),e=ceil(getHeight(e)/t,DECIMALS),n=n+2*ceil((o-1)*n/2,DECIMALS),o=ceil((o-1)*e/2,DECIMALS);return getForViewAndSize(i,t,0,[n,e+2*o])}export default ImageSource;export{ImageSourceEventType,ImageSourceEvent,defaultImageLoadFunction,getRequestExtent};