//@tag dom,core

/**
 * An Identifiable mixin.
 * @private
 */
Ext.define('Ext.mixin.Identifiable', {
    statics: {
        uniqueIds: {}
    },

    isIdentifiable: true,

    mixinId: 'identifiable',

    idCleanRegex: /\.|[^\w\-]/g,

    defaultIdPrefix: 'ext-',

    defaultIdSeparator: '-',

    getOptimizedId: function() {
        return this.id;
    },

    getUniqueId: function() {
        var id = this.id,
            prototype, separator, xtype, uniqueIds, prefix;

        // Cannot test falsiness. Zero is a valid ID.
        if (!(id || id === 0)) {
            prototype = this.self.prototype;
            separator = this.defaultIdSeparator;

            uniqueIds = Ext.mixin.Identifiable.uniqueIds;

            if (!prototype.hasOwnProperty('identifiablePrefix')) {
                xtype = this.xtype;

                if (xtype) {
                    prefix = this.defaultIdPrefix + xtype.replace(this.idCleanRegex, separator) + separator;
                } else if (!(prefix = prototype.$className)) {
                    prefix = this.defaultIdPrefix + 'anonymous' + separator;
                } else {
                    prefix = prefix.replace(this.idCleanRegex, separator).toLowerCase() + separator;
                }

                prototype.identifiablePrefix = prefix;
            }

            prefix = this.identifiablePrefix;

            if (!uniqueIds.hasOwnProperty(prefix)) {
                uniqueIds[prefix] = 0;
            }

            // The double assignment here and in setId is intentional to workaround a JIT 
            // issue that prevents me.id from being assigned in random scenarios. The issue
            // occurs on 4th gen iPads and lower, possibly other older iOS devices. See EXTJS-16494.
            id = this.id = this.id = prefix + (++uniqueIds[prefix]);
        }

        this.getUniqueId = this.getOptimizedId;

        return id;
    },

    setId: function(id) {
        // See getUniqueId()
        this.id = this.id = id;
    },

    /**
     * Retrieves the id of this component. Will autogenerate an id if one has not already been set.
     * @return {String} id
     */
    getId: function() {
        var id = this.id;

        if (!id) {
            id = this.getUniqueId();
        }

        this.getId = this.getOptimizedId;

        return id;
    }
});
