// @tag dom,core
 
/* eslint-disable max-len */
/**
 * An Identifiable mixin.
 * @private
 */
Ext.define('Ext.mixin.Identifiable', function(Identifiable) { return { // eslint-disable-line brace-style
/* eslint-enable max-len */
    isIdentifiable: true,
 
    mixinId: 'identifiable',
 
    /**
     * Retrieves the `id`. This method Will auto-generate an id if one has not already
     * been configured.
     * @return {String} id
     */
    getId: function() {
        var me = this,
            id = me.id,
            cfg;
 
        if (!(id || id === 0)) {
            cfg = me.initialConfig;
 
            // The id config can be requested so early (e.g., by stateful) that the
            // property has not been put on the instance yet.
            if (cfg && cfg.id) {
                id = cfg.id;
            }
            else {
                id = me.generateAutoId();
                me.autoGenId = true;
            }
 
            me.setId(id);
        }
 
        me.getId = Identifiable._getId;
 
        return id;
    },
 
    setId: function(id) {
        // 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.
        this.id = this.id = id;
    },
 
    privates: {
        statics: {
            _idCleanRe: /\.|[^\w-]/g,
            uniqueIds: {},
 
            _getId: function() {
                return this.id;
            }
        },
 
        defaultIdPrefix: 'ext-',
 
        defaultIdSeparator: '-',
 
        id: null,
 
        /**
         * @property {Boolean} autoGenId
         * `true` indicates an `id` was auto-generated rather than provided by configuration.
         * @private
         * @since 6.7.0
         */
        autoGenId: false,
 
        generateAutoId: function() {
            var me = this,
                prototype = me.self.prototype,
                sep = me.defaultIdSeparator,
                uniqueIds = Identifiable.uniqueIds,
                cleanRe, defaultIdPrefix, prefix, xtype;
 
            if (!prototype.hasOwnProperty('identifiablePrefix')) {
                cleanRe = Identifiable._idCleanRe;
                defaultIdPrefix = me.defaultIdPrefix;
                xtype = me.xtype;
 
                if (xtype) {
                    prefix = defaultIdPrefix + xtype.replace(cleanRe, sep) + sep;
                }
                else if (!(prefix = prototype.$className)) {
                    prefix = defaultIdPrefix + 'anonymous' + sep;
                }
                else {
                    prefix = prefix.replace(cleanRe, sep).toLowerCase() + sep;
                }
 
                prototype.identifiablePrefix = prefix;
            }
 
            prefix = me.identifiablePrefix;
 
            if (!uniqueIds.hasOwnProperty(prefix)) {
                uniqueIds[prefix] = 0;
            }
 
            return prefix + (++uniqueIds[prefix]);
        }
    } // privates
};
});