/**
 * This base class can be used by derived classes to dynamically require Google API's.
 */
Ext.define('Ext.ux.google.Api', {
    mixins: [
        'Ext.mixin.Mashup'
    ],
 
    requiredScripts: [
        '//www.google.com/jsapi'
    ],
 
    statics: {
        loadedModules: {
            /*
             *  feeds: [ callback1, callback2, .... ]  transitions to -> feeds : true  (when complete)
             */
        }
    },
 
    onClassExtended: function(cls, data, hooks) {
        var onBeforeClassCreated = hooks.onBeforeCreated,
            Api = this; // the Ext.ux.google.Api class
 
        hooks.onBeforeCreated = function(cls, data) {
            var me = this,
                apis = [],
                requiresGoogle = Ext.Array.from(data.requiresGoogle),
                loadedModules = Api.loadedModules,
                remaining = 0,
                callback = function () {
                    if (! --remaining) {
                        onBeforeClassCreated.call(me, cls, data, hooks);
                    }
                    Ext.env.Ready.unblock();
                },
                api, i, length;
 
            /*
             *  requiresGoogle: [
             *      'feeds',
             *      { api: 'feeds', version: '1.x',
             *        callback : fn, nocss : true }  //optionals
             *  ]
             */
            length = requiresGoogle.length;
 
            for (= 0; i < length; ++i) {
                if (Ext.isString(api = requiresGoogle[i])) {
                    apis.push({ api: api });
                } else if(Ext.isObject(api)) {
                    apis.push(Ext.apply({}, api));
                }
            }
 
            Ext.each(apis, function (api) {
                var name = api.api,
                    version = String(api.version || '1.x'),
                    module = loadedModules[name];
 
                if (!module) {
                    ++remaining;
                    Ext.env.Ready.block();
                    loadedModules[name] = module = [ callback ].concat(api.callback || []);
 
                    delete api.api;
                    delete api.version;
 
                    if (!window.google) {
                        Ext.raise("'google' is not defined.");
                        return false;
                    }
 
                    google.load(
                        name,
                        version,
                        Ext.applyIf({
                            callback    : function () {
                                loadedModules[name] = true;
 
                                for (var n = module.length; n-- > 0; ) {
                                    module[n]();    //iterate callbacks in reverse
                                }
                            }
                        }, api)
                    );
 
                } else if (module !== true) {
                    module.push(callback);
                }
            });
 
            if (!remaining) {
                onBeforeClassCreated.call(me, cls, data, hooks);
            }
        };
    }
});