import Ajax from 'core/Ajax';
import { emptyImageUrl, hasOwn } from 'core/util';
import TileLayer from 'layer/tile/TileLayer';
import TileLayerCanvasRenderer from './TileLayerCanvasRenderer';
import ImageGLRenderable from '../ImageGLRenderable';
import Browser from 'core/Browser';
import Canvas from 'core/Canvas';

/**
 * @classdesc
 * Renderer class based on HTML5 WebGL for TileLayers
 * @class
 * @protected
 * @memberOf renderer
 * @extends {renderer.TileLayerCanvasRenderer}
 * @param {TileLayer} layer - TileLayer to render
 */
class TileLayerGLRenderer extends ImageGLRenderable(TileLayerCanvasRenderer) {

    //override to set to always drawable
    isDrawable() {
        return true;
    }

    needToRedraw() {
        const map = this.getMap();
        if (this._gl() && !map.getPitch() && map.isZooming() && !map.isMoving() && !map.isRotating()) {
            return true;
        }
        return super.needToRedraw();
    }

    drawTile(tileInfo, tileImage) {
        if (!this._gl()) {
            // fall back to canvas 2D
            super.drawTile(tileInfo, tileImage);
            return;
        }
        if (tileImage.src === emptyImageUrl) {
            return;
        }
        const map = this.getMap();
        if (!tileInfo || !map) {
            return;
        }
        const point = tileInfo.point,
            tileZoom = tileInfo.z;
        const scale = map.getGLScale(tileZoom),
            pp = point.multi(scale),
            tileSize = this.layer.getTileSize();
        const opacity = this.getTileOpacity(tileImage);
        const x = pp.x,
            y = pp.y,
            w = tileSize['width'] * scale,
            h = tileSize['height'] * scale;

        this.drawGLImage(tileImage, x, y, w, h, opacity);

        if (opacity < 1) {
            this.setToRedraw();
        } else {
            this.setCanvasUpdated();
        }
    }

    loadTileImage(tileImage, url) {
        return Ajax.getImage(tileImage, url);
    }


    // prepare gl, create program, create buffers and fill unchanged data: image samplers, texture coordinates
    onCanvasCreate() {
        this.prepareGLCanvas();
    }

    resizeCanvas(canvasSize) {
        if (!this.canvas) {
            return;
        }
        super.resizeCanvas(canvasSize);
        this.resizeGLCanvas();
    }

    clearCanvas() {
        if (!this.canvas) {
            return;
        }
        super.clearCanvas();
        this.clearGLCanvas();
    }

    getCanvasImage() {
        if (this._gl() && this.isCanvasUpdated()) {
            const ctx = this.context;
            if (Browser.retina) {
                ctx.save();
                ctx.scale(1 / 2, 1 / 2);
            }
            // draw gl canvas on layer canvas
            ctx.drawImage(this.glCanvas, 0, 0);
            if (Browser.retina) {
                ctx.restore();
            }
        }
        return super.getCanvasImage();
    }

    // decide whether the layer is renderer with gl.
    // when map is pitching, or fragmentShader is set in options
    _gl() {
        return this.getMap() && !!this.getMap().getPitch() || this.layer && !!this.layer.options['fragmentShader'];
    }

    _drawBackground() {
        if (this.background) {
            if (!this._gl()) {
                super._drawBackground();
            } else if (!this.background.nw) {
                //ignore if background is saved in canvas mode
                const map = this.getMap();
                const extent = map.getContainerExtent();
                for (const p in this.background) {
                    if (p === 'canvas') {
                        continue;
                    }
                    const parentTile = this.background[p];

                    if (this.layer._isTileInExtent(parentTile.info, extent)) {
                        this.drawTile(parentTile.info, parentTile.image);
                    }
                }
                if (!map.isZooming()) {
                    let backCanvas = this.background.canvas;
                    if (!backCanvas) {
                        backCanvas = Canvas.copy(this.glCanvas);
                        this.background.canvas = backCanvas;
                    } else {
                        backCanvas.width = this.glCanvas.width;
                        backCanvas.height = this.glCanvas.height;
                        backCanvas.getContext('2d').drawImage(this.glCanvas, 0, 0);
                        const ctx = this.context;
                        if (Browser.retina) {
                            ctx.save();
                            ctx.scale(1 / 2, 1 / 2);
                        }
                        ctx.drawImage(backCanvas, 0, 0);
                        if (Browser.retina) {
                            ctx.restore();
                        }
                    }
                }
            }
        }
    }

    _saveBackground() {
        if (!this._gl()) {
            super._saveBackground();
            return;
        }
        this.background = {};
        const cache = this._tileRended;
        for (const p in cache) {
            const tile = cache[p];
            if (hasOwn(cache, p) && tile && tile.image.current) {
                tile.image.loadTime = 0;
                this.background[p] = tile;
            }
        }
    }

    deleteTile(tile) {
        super.deleteTile(tile);
        if (tile && !tile.current && tile.texture) {
            this.saveTexture(tile.texture);
            this.saveBuffer(tile.buffer);
            delete tile.texture;
            delete tile.buffer;
        }
    }

    onRemove() {
        this.removeGLCanvas();
    }
}

TileLayer.registerRenderer('gl', TileLayerGLRenderer);

export default TileLayerGLRenderer;



@@ -2478,32 +2478,33 @@
 ) %7B%0A        if (
+!
 this._gl() && th
@@ -2497,20 +2497,125 @@
 is._gl()
- && 
+) %7B%0A            return super.getCanvasImage();%0A        %7D%0A        if (this.layer.getMask()) %7B%0A            if (
 this.isC
@@ -2636,32 +2636,36 @@
 ) %7B%0A            
+ 
+   
 const ctx = this
@@ -2678,32 +2678,36 @@
 xt;%0A            
+    
 if (Browser.reti
@@ -2720,32 +2720,36 @@
                 
+   
+ 
 ctx.save();%0A    
@@ -2736,32 +2736,36 @@
     ctx.save();%0A
+    
                 
@@ -2781,32 +2781,36 @@
 (1 / 2, 1 / 2);%0A
+    
             %7D%0A  
@@ -2815,24 +2815,28 @@
             
+    
 // draw gl c
@@ -2857,16 +2857,20 @@
  canvas%0A
+    
         
@@ -2913,32 +2913,36 @@
 0);%0A            
+ 
+   
 if (Browser.reti
@@ -2955,32 +2955,36 @@
                 
+    
 ctx.restore();%0A 
@@ -2990,34 +2990,41 @@
             
+  
-%7D%0A
+  %7D%0A   
         
 %7D%0A        re
@@ -3003,34 +3003,39 @@
    %7D%0A           
+ 
 %7D%0A
+    
         return s
@@ -3053,24 +3053,162 @@
 vasImage();%0A
+        %7D else %7B%0A            const img = super.getCanvasImage();%0A            img.image = this.glCanvas;%0A            return img;%0A        %7D%0A
     %7D%0A%0A    /

update getCanvasImage to save drawImage calls