/**
 * @class Ext.draw.sprite.Image
 * @extends Ext.draw.sprite.Rect
 *
 * A sprite that represents an image.
 */
Ext.define('Ext.draw.sprite.Image', {
    extend: 'Ext.draw.sprite.Rect',
    alias: 'sprite.image',
    type: 'image',
    statics: {
        imageLoaders: {}
    },
 
    inheritableStatics: {
        def: {
            processors: {
                /**
                 * @cfg {String} [src=''] The image source of the sprite.
                 */
                src: 'string'
                /**
                 * @private
                 * @cfg {Number} radius
                 */
            },
            triggers: {
                src: 'src'
            },
            updaters: {
                src: 'updateSource'
            },
            defaults: {
                src: '',
                /**
                 * @cfg {Number} [width=null] The width of the image.
                 * For consistent image size on all devices the width must be explicitly set.
                 * Otherwise the natural image width devided by the device pixel ratio
                 * (for a crisp looking image) will be used as the width of the sprite.
                 */
                width: null,
                /**
                 * @cfg {Number} [height=null] The height of the image.
                 * For consistent image size on all devices the height must be explicitly set.
                 * Otherwise the natural image height devided by the device pixel ratio
                 * (for a crisp looking image) will be used as the height of the sprite.
                 */
                height: null
            }
        }
    },
 
    updateSurface: function(surface) {
        if (surface) {
            this.updateSource(this.attr);
        }
    },
 
    updateSource: function(attr) {
        var me = this,
            src = attr.src,
            surface = me.getSurface(),
            loadingStub = Ext.draw.sprite.Image.imageLoaders[src],
            width = attr.width,
            height = attr.height,
            imageLoader,
            i;
 
        if (!surface) {
            // First time this is called the sprite won't have a surface yet.
            return;
        }
 
        if (!loadingStub) {
            imageLoader = new Image();
            loadingStub = Ext.draw.sprite.Image.imageLoaders[src] = {
                image: imageLoader,
                done: false,
                pendingSprites: [me],
                pendingSurfaces: [surface]
            };
            imageLoader.width = width;
            imageLoader.height = height;
 
            imageLoader.onload = function() {
                var item;
 
                if (!loadingStub.done) {
                    loadingStub.done = true;
 
                    for (= 0; i < loadingStub.pendingSprites.length; i++) {
                        item = loadingStub.pendingSprites[i];
 
                        if (!item.destroyed) {
                            item.setDirty(true);
                        }
                    }
 
                    for (= 0; i < loadingStub.pendingSurfaces.length; i++) {
                        item = loadingStub.pendingSurfaces[i];
 
                        if (!item.destroyed) {
                            item.renderFrame();
                        }
                    }
                }
            };
 
            imageLoader.src = src;
        }
        else {
            Ext.Array.include(loadingStub.pendingSprites, me);
            Ext.Array.include(loadingStub.pendingSurfaces, surface);
        }
    },
 
    render: function(surface, ctx) {
        var me = this,
            attr = me.attr,
            mat = attr.matrix,
            src = attr.src,
            x = attr.x,
            y = attr.y,
            width = attr.width,
            height = attr.height,
            loadingStub = Ext.draw.sprite.Image.imageLoaders[src],
            image;
 
        if (loadingStub && loadingStub.done) {
            mat.toContext(ctx);
            image = loadingStub.image;
            ctx.drawImage(
                image, x, y,
                width || (image.naturalWidth || image.width) / surface.devicePixelRatio,
                height || (image.naturalHeight || image.height) / surface.devicePixelRatio
            );
        }
 
        //<debug>
        // eslint-disable-next-line vars-on-top
        var debug = attr.debug || this.statics().debug || Ext.draw.sprite.Sprite.debug;
 
        if (debug && debug.bbox) {
            this.renderBBox(surface, ctx);
        }
        //</debug>
    },
 
    /**
     * @private
     */
    isVisible: function() {
        var attr = this.attr,
            parent = this.getParent(),
            hasParent = parent && (parent.isSurface || parent.isVisible()),
            isSeen = hasParent && !attr.hidden && attr.globalAlpha;
 
        return !!isSeen;
    }
});