/**
 * primitive inheritance
 *
 * @param {Object} parentCtor
 *
 * @TODO Move to library!
 */
Function.prototype.inherits = function(parentCtor) {
  function tempCtor() {};
  tempCtor.prototype = parentCtor.prototype;
  this.superClass_ = parentCtor.prototype;
  this.prototype = new tempCtor();
  this.prototype.constructor = this;
};

/**
 * @namespace gadgets
 */
var gadgets = gadgets || {};
/**
 * remoteServiceFactory
 *
 * @class returns service instances for any view
 * @name gadgets.remoteServiceFactory
 *
 */
gadgets.remoteServiceFactory = function () {

    /**
     * storage for the services
     *
     * @var object
     */
    var _serviceRegistry = {};

    /**
     * @var object
     */
    var _services = {};

    /**
     * Providing remote Services for the iframes
     * currently supported:
     *
     * requestNavigateTo
     * resize_iframe
     * set_title
     *
     */
    _services.basic = function(){
    };

    /**
     * Generating a url for another view of a Gadget
     *
     * @param {String} view
     * @return {String} url
     *
     */
    _services.basic.prototype._buildUrlForSandboxView = function (view, params, gadget) {
        var url;

        url = gadgets.baseUrl;

        var type = 'link';
        var close = false;

        switch (view.toLowerCase()) {
            case 'nobleprofile'  :
                if (gadget.profileId) {
                    url += gadgets.sandbox.url.profile + gadget.aid + '/' + gadget.v;
                    url += '/owner/' + gadget.profileId;
                } else {
                    return false;
                }
                break;
            case 'profile'  :
                if (gadget.profileId) {
                    url += gadgets.sandbox.url.profile + gadget.aid + '/' + gadget.v;
                    url += '/owner/' + gadget.profileId;
                } else {
                    return false;
                }
                break;
            case 'start'    :
                return false;
                break;
            case 'group'    :
            case 'groupinstallation':
                if (gadget.groupId) {
                    url += gadgets.sandbox.url.group + gadget.aid  + '/' + gadget.v;
                } else {
                    return false;
                }
                break;
            case 'popup'    :
            case 'popupinstallation' :
                url += gadgets.sandbox.url.popup + gadget.aid  + '/' + gadget.v;
                if (gadget.profileId) {
                    url += '/owner/' + gadget.profileId;
                }
                type = 'popup';
                break;
            case 'integration'    :
            case 'integrationinstallation':
                url += gadgets.sandbox.url.integration + gadget.aid  + '/' + gadget.v;
                break;
            case 'preview'  :
                url += gadgets.sandbox.url.preview + gadget.aid  + '/' + gadget.v;
                close = true;
                break;
            case 'canvas'   :
            case 'nobleprofilecanvas':
                if (gadget.profileId) {
                    url += gadgets.sandbox.url.canvas + gadget.aid + '/' + gadget.v;
                    url += '/owner/' + gadget.profileId;
                } else {
                    return false;
                }
                break;
            case 'groupcanvas' :
            case 'groupcanvasinstallation':
                if (gadget.groupId) {
                    url += gadgets.sandbox.url.groupcanvas + gadget.aid + '/' + gadget.v;
                } else {
                    return false;
                }
                break;
            default         :
                return false;
                break;
        }
        
        if (params) {
            var paramStr = JSON.stringify(params);
            if (paramStr.length > 0) {
               // we have to double encode here so that we encode strings with slashes
               // in a way that the phx url parser will not split the json string
               // there
               url += '/params/' + encodeURIComponent(encodeURIComponent(paramStr));
            }
        }

        return {'type': type, 'url': url, 'close': close};
    };

    /**
     * Generating a url for another view of a Gadget
     *
     * @param {String} view
     * @return {String} url
     *
     */
    _services.basic.prototype._buildUrlForView = function (view, params, gadget) {
        if (gadgets.sandbox) {
            return this._buildUrlForSandboxView(view, params, gadget);
        }

        var url;

        url = gadgets.baseUrl;

        var type = 'link';
        var close = false;
        
        switch (view.toLowerCase()) {
            case 'nobleprofile'  :
                if (gadget.profileId) {
                    url += '/Profile/' + gadget.profileId;
                } else {
                    return false;
                }
                break;
            case 'profile'  :
                if (gadget.profileId) {
                    url += '/Gadgets/MyGallery/' + gadget.profileId + '/' + gadget.mid;
                } else {
                    return false;
                }
                break;
            case 'start'    :
                return false;
                break;
            case 'group'    :
            case 'groupinstallation':
                if (gadget.groupId) {
                    url += '/Groups/Overview/' + gadget.groupId;
                } else {
                    return false;
                }
                break;
            case 'popup'    :
            case 'popupinstallation' :
                url += '/Gadgets/Popup/' + gadget.aid;
                if (gadget.profileId) {
                    url += '/profileId/' + gadget.profileId;
                }
                type = 'popup';
                break;
            case 'integration'    :
            case 'integrationinstallation':
                url += '/Gadgets/Integration/' + gadget.aid;
                break;
            case 'preview'  :
                url += '/Gadgets/Install/' + gadget.aid + '/';
                close = true;
                break;
            case 'canvas'   :
            case 'nobleprofilecanvas':
                if (gadget.view == 'embed') {
                    url += '/Gadgets/Install/' + gadget.aid + '/';
                } else if (gadget.profileId) {
                    url += '/Gadgets/Canvas/' + gadget.mid;
                    url += '/profileId/' + gadget.profileId;
                    if (gadget.position == 'front') {
                        url += '/r/profile';
                    }
                } else {
                    return false;
                }
                break;
            case 'groupcanvas' :
            case 'groupcanvasinstallation':
                if (gadget.groupId) {
                    url += '/Gadgets/GroupCanvas/' + gadget.mid;
                    url += '/groupId/' + gadget.groupId;
                } else {
                    return false;
                }
                break;
            default         :
                return false;
                break;
        }

        if (params) {
            var paramStr = JSON.stringify(params);
            if (paramStr.length > 0) {
               // we have to double encode here so that we encode strings with slashes
               // in a way that the phx url parser will not split the json string
               // there
               url += '/params/' + encodeURIComponent(encodeURIComponent(paramStr));
            }
        }

        return {'type': type, 'url': url, 'close': close};
    };

    _services.basic.prototype._convertPossibleOsIdAlias = function(possibleAlias, gadget) {
        var osId = possibleAlias;
        var alias = possibleAlias.toLowerCase();
        
        if (alias == 'owner') {
            osId = gadget.o;
        } else if (alias == 'viewer') {
            osId = gadget.vw;
        }

        return osId;
    }

    _services.basic.prototype._getEncodedRecipientString = function(recipients, gadget) {
        var validRecipients = new Array();
        var recipient;
        var recipientString = '';

        if (typeof recipients === 'string') {
            recipient = this._convertPossibleOsIdAlias(recipients, gadget);
            validRecipients.push(encodeURIComponent(recipient));
        } else if (typeof recipients === 'object') {
            for (var i in recipients) {
                recipient = this._convertPossibleOsIdAlias(recipients[i], gadget);
                validRecipients.push(encodeURIComponent(recipient));
            }
        }

        if (recipients.length > 0) {
            recipientString = '&openSocialIds[]=' + validRecipients.join('&openSocialIds[]=');
        }

        return recipientString;
    }

    _services.basic.prototype.showPaymentInterstitial = function (args, gadget, callback) {
        Phx.UI.Dialog.ButtonDialog(i18n.getText('gadgets_payment_dialog_header'),{
            message: i18n.getPText('gadgets_payment_dialog') ,
            buttons:[
                new Phx.UI.Button.Submit(i18n.getText('gadgets_payment_proceed'), true),
                new Phx.UI.Button.Submit(i18n.getText('gadgets_payment_cancel'), false)
            ],
            events: {
                onButtonClicked: function (result)
                {
                    if('false' === result || false === result) {
                        if (typeof callback === 'function') {
                            callback(false);
                        }
                    }
                    if (typeof callback === 'function') {
                        callback(true);
                    }
                }
            }
        }).show();
    };

    _services.basic.prototype.getPermissions = function (args, gadget, callback) {
        var userId = args[0].userId;
        if (userId === 'VIEWER') {
            userId = gadget.vw;
        } else if (userId === 'OWNER') {
            userId = gadget.o;
        }
        var params = '&installationId=' + gadget.mid
            + '&gadgetId=' + gadget.aid
            + '&userId=' + userId;

        Phx.Application.RequestRegistry.append({
            1: 'Gadgets_getPermissions',
            2: function(response) {
                callback(response.module.data.permissions);
            },
            3: '',
            4: params
        });
    };

    _services.basic.prototype.writeFeedEntry = function (args, gadget, callback) {
        var params = '&message=' + encodeURIComponent(args[0].body) + '&url=' + encodeURIComponent(args[0].url);
        params += '&gadgetId=' + gadget.aid;
        params += '&gadgetRevisionId=' + gadget.v;
        if (args[0].body.length > 140) {
            callback({'result': false, 'msg' : 'invalid body length'});
            return;
        }
        Phx.Application.RequestRegistry.append({
            1:  'Gadgets_feedEntryDialog',
            2: function(response) {
                    var _htmlDialog = Phx.UI.Dialog.HTML(i18n.getText('feed_write_dialog'), {
                        message : response.module.data.html
                    });
                   
                    _htmlDialog.show();

                    $('.Write-Feed-Text').html(Phx.Util.linkify($('.Write-Feed-Text').html(), {wrap: 38, embedActive: true, maxItems: 1}));
                    Phx.Util.OEmbedThumb($('.Write-Feed-Text').parent());
                    var _close = function(response, msg) {
                        _htmlDialog.close();
                        if (typeof callback === 'function') {
                            callback({'result': response, 'msg' : msg});
                        }
                    };

                    $('#Write-Feed-Message-Close').unbind('click').bind('click', function() {
                        _close(false, 'user canceled request');
                    });

                    $('#Write-Feed-Message-Save').unbind('click').bind('click', function() {
                        Phx.Application.RequestRegistry.append({
                            1:  'Gadgets_feedEntry',
                            2: function() {
                                _close(true);
                            },
                            3: '',
                            4: params
                        });
                    });
            },
            3:  '',
            4:  params
        });
    };

    _services.basic.prototype.updatePerson = function(args, gadget, callback) {
        var params = '&gadgetId=' + gadget.aid;
        params += '&gadgetRevisionId=' + gadget.v;
        params += '&newImage=' + encodeURIComponent(args[0].person.fields_.thumbnailUrl);
        if (gadgets.sandbox) {
            params += '&sandbox=1';
        }
        Phx.Application.RequestRegistry.append({
            1:  'Profile_getUpdateImageForm',
            2: function(response) {
                var _htmlDialog = Phx.UI.Dialog.HTML(i18n.getText('upload_profile_picture'), {
                    message : response.module.data.html
                });

                _htmlDialog.show();

                $('#close-dialog-save').click(function() {
                    if (gadgets.sandbox) {
                        _htmlDialog.close();
                        callback(true);
                        return;
                    }
                    Phx.Application.RequestRegistry.append({
                        1:  'Profile_updateImage',
                        2: function(response) {
                            _htmlDialog.close();
                            callback(true);
                        },
                        3: '',
                        4: params
                    });
                });
                $('#close-dialog-cancel').click(function() {
                    _htmlDialog.close();
                    callback(false);
                });
            },
            3: '',
            4: params
        });
    };

    _services.basic.prototype.sendPublicMessage = function (args, gadget, callback) {
        var recipientString = this._getEncodedRecipientString(args[0].recipients, gadget);

        var params = '&disableMultiRec=0&message=' + encodeURIComponent(args[0].body)
                    + recipientString
                    + '&gadgetId=' + gadget.aid + '&gadgetRevisionId=' + gadget.v;

        Phx.Application.RequestRegistry.append({
            1:  'Gadgets_pinboardMessageDialog',
            2:  function(response) {
                    var _htmlDialog = Phx.UI.Dialog.HTML(i18n.getText('pinboard_write_dialog'), {
                        message : response.module.data.html
                    });

                    _htmlDialog.show();
                    
                    var maxFriendsCount = $('#maxRecipientCount').val();
                    var writeMessageConfig = {
                        'maxFriendsCount' : parseInt(maxFriendsCount),
                        'maxFriendsListsCount' : 0
                    };

                    Phx.Application.Modules.WriteMessage.resetFriendList();
                    Phx.Application.Modules.WriteMessage.init(writeMessageConfig);

                    var messageContainer = $('.dialog-content .pinboard-entry-text');
                    messageContainer.html(Phx.Util.linkify(messageContainer.html(), {embedActive: true}, true));
                    Phx.Util.OEmbed(messageContainer, 300, 400);

                    $('#Write-Pinboard-Message-Close').unbind('click').bind('click', function() {
                        _htmlDialog.close();
                        if (typeof callback === 'function') {
                            callback(false);
                        }
                    });

                    $('#Write-Pinboard-Message-Send').unbind('click').bind('click', function() {
                        var writeParams = '&gadgetId=' + gadget.aid + '&message=' + encodeURIComponent(args[0].body) + '&gadgetRevisionId=' + gadget.v;

                        var writeRecipients = $('.recipientIds');

                        writeRecipients.each(function() {
                           writeParams += '&recipientIds[]=' + $(this).val();
                        });

                        Phx.Application.RequestRegistry.append({
                            1:  'Gadgets_pinboardMessage',
                            2:  function(response) {
                                    _htmlDialog.close();
                                    if (typeof callback === 'function') {
                                        callback(response.module.data.osRecipients);
                                    }
                                },
                            3:  '',
                            4:  writeParams
                        });
                    });
                },
            3:  '',
            4:  params
        });
    };

    _services.basic.prototype.sendPrivateMessage = function (args, gadget, callback) {
        if (gadgets.sandbox) {
            var sandboxParams = '&message=' + encodeURIComponent(args[0].body)
                    + '&gadgetId=' + gadget.aid
                    + '&gadgetRevisionId=' + gadget.v;

            Phx.Application.RequestRegistry.append({
                1:  'Gadgets_messagePreview',
                2:  function(response) {
                        var _htmlDialog = Phx.UI.Dialog.HTML('Preview Message', {
                            message : response.module.data.html
                        });

                        _htmlDialog.show();

                        var messageContainer = $('.dialog-content #Preview-Message');
                        messageContainer.html(Phx.Util.linkify(messageContainer.html(), {embedActive: true}, true));
                        Phx.Util.OEmbed(messageContainer, 300, 400);

                        $('#MessagePreview-Close').unbind('click').bind('click', function() {
                            _htmlDialog.close();
                            if (typeof callback === 'function') {
                                callback(true);
                            }
                        });
                    },
                3:  '',
                4:  sandboxParams
            });
            return;
        }

        var recipientString = this._getEncodedRecipientString(args[0].recipients, gadget);

        var params = '&message=' + encodeURIComponent(args[0].body)
                    + recipientString
                    + '&gadgetId=' + gadget.aid;
                
        Phx.Application.RequestRegistry.append({
            1:  'Gadgets_replyMessage',
            2:  function(response) {
                    Phx.Application.Modules.WriteMessage.resetFriendList();
                    Phx.Application.Modules.WriteMessage.showReplyMessageDialog(response, args[0].subject, callback);
                    Phx.Application.Modules.WriteMessage.init();
                },
            3:  '',
            4:  params
        });
    };

    _services.basic.prototype.getEmbedUrl = function (args, gadget, callback) {
        callback(_services.basic.prototype._getEmbedUrl(gadget, args));
    };

    _services.basic.prototype.getStaticContentUrl = function (args, gadget, callback) {
        callback(_services.basic.prototype._getStaticContentEmbedUrl(gadget, args));
    };

    _services.basic.prototype.getStaticContent = function (args, gadget, callback) {
        var params = '&gadgetId=' + gadget.aid;
        params += '&gadgetRevisionId=' + gadget.v;
        params += '&key=' +  encodeURIComponent(args[0].key);
        if (args[0].params) {
            params += '&params=' + encodeURIComponent(JSON.stringify(args[0].params));
        }
        Phx.Application.RequestRegistry.append({
            1:  'Gadgets_getStaticKey',
            2:  function(response) {
                    callback(response.module.data.content);
                },
            3:  '',
            4:  params
        });
    };

    _services.basic.prototype.sendEmbed = function (args, gadget, callback) {
        if (gadgets.sandbox) {
            var params = '&gadgetId=' + gadget.aid;
            params += '&ownerId=' + gadget.o;
            params += '&gadgetRevisionId=' + gadget.v;
            params += '&url=' +  encodeURIComponent(args[0].url)
            Phx.Application.RequestRegistry.append({
                1:  'GadgetDeveloper_getEmbed',
                2:  function(response) {
                        $('#Preview-Embed-Container').html(response.module.data.html);
                        gadgets.gadgetManager.setAllGadgets(gadgets.data);
                        Phx.Application.Modules.gadgetscontroller.generateGadgets();
                    },
                3:  '',
                4:  params
            });
            return;
        }
        
        Phx.Application.Modules.Embed.handleGadgetCallback(args[0].url);
    };

    _services.basic.prototype._getStaticContentEmbedUrl = function(gadget, args) {
        if (gadgets.sandbox) {
            var sbUrl = 'http://' + window.location.host + '/GadgetDeveloper/Static/' + gadget.aid + '/' + gadget.v + '/' + encodeURIComponent(args[0].key);
            if (args[0].params) {
                sbUrl += '/' + encodeURIComponent(JSON.stringify(args[0].params));
            }
            return sbUrl;
        }
        var url = 'http://' + window.location.host + '/Gadgets/Static/' + gadget.aid + '/' + encodeURIComponent(args[0].key);
        if (args[0].params) {
            url += '/' + encodeURIComponent(JSON.stringify(args[0].params));
        }
        return url;
    };

    _services.basic.prototype._getEmbedUrl = function(gadget, args) {
        var url;
        if (gadget.profileId) {
            url = 'http://' + window.location.host + '/Gadgets/Embed/' + gadget.profileId + '/' + gadget.mid;
        } else {
            url = 'http://' + window.location.host + '/Gadgets/IntegrationEmbed/' + gadget.vw + '/' + gadget.aid;
        }
        if (gadgets.sandbox) {
            url = 'http://' + window.location.host + '/GadgetDeveloper/Embed/' + gadget.vw + '/' + gadget.aid + '/' + gadget.v;
        }
        if (args[0].param) {
            url += '/' + encodeURIComponent(encodeURIComponent(args[0].param));
        }
        return url;
    };
    
    _services.basic.prototype.suggest   = function (args, gadget, callback) {
        
        var urlParams = {};
        if (args && args[0] && args[0].subject && typeof args[0].subject == 'string') {
            urlParams.subject = args[0].subject;
        }

        if (args && args[0] && args[0].message && typeof args[0].message == 'string') {
            urlParams.message = args[0].message;
        }

        if (args && args[0] && args[0].token && typeof args[0].token == 'string') {
            urlParams.token = args[0].token;
        }
        
        if (args && args[0] && args[0].image && typeof args[0].image == 'string') {
            urlParams.image = args[0].image;
        }

        urlParams = Phx.Util.encodeValues(urlParams);

        if (args[0].recipients) {
            var recipientString = this._getEncodedRecipientString(args[0].recipients, gadget);
            urlParams += recipientString;
        }
        gadgets.models.main.getSuggestDialog(gadget, urlParams);
    };

    _services.basic.prototype._vcardUpdated = function(callback, result) {
        if (typeof callback === 'function') {
            callback(result);
        }
        return;
    };

    _services.basic.prototype.getAdTag = function (args,gadget, callback) {
        var params = '&gadgetId=' + gadget.aid + '&adCode=' + args[0].adCode;
        Phx.Application.RequestRegistry.append({
            1:  'Gadgets_getAdTag',
            2:  function(response) {
                    if (typeof callback === 'function') {
                        callback(response.module.data.adTag);
                    }
                },
            3:  '',
            4:  params
        });
    };

    _services.basic.prototype.updateVcard = function (args,gadget, callback) {
        if (gadgets.sandbox) {
            if (typeof callback === 'function') {
                alert('Vcard edited');
                _services.basic.prototype._vcardUpdated(callback, true);
            }
            return;
        }

        Phx.Application.Modules.vcard.showConnectVcardForm(gadget.aid, gadget.title, args[0].requiredFields, function(result) {
            _services.basic.prototype._vcardUpdated(callback, result);
        });
        
    };

    _services.basic.prototype.setHeight = function (args, gadget, callback) {
            if(args[0] < this.maxHeight) {
                $('#remote-iframe-' + gadget.mid).height(args[0]);
            } else {
                $('#remote-iframe-' + gadget.mid).height(this.maxHeight);
            }
    };


    /**
     *
     *
     */
    _services.basic.prototype.setPref = function (args, gadget, callback) {
        if (gadget.owner != gadget.viewer) {
            return;
        }
        
        gadget.prefs[args[1]] = args[2];

        gadgets.models.main.savePreferences(gadget.mid, JSON.stringify(gadget.prefs), function (responseData) {
            $('#gadgets-gadget-prefs-' + gadget.mid + ' form').replace(responseData.module.data.html);
        });
    };

    /**
     * Setting the title of the gadgets chrome
     *
     */
    _services.basic.prototype.setTitle = function (args, gadget, callback) {
        $('#gadgets-gadget-title-' + gadget.mid).text(args[0]);
    };

    _services.basic.prototype.invite = function (args, gadget, callback) {
        this.suggest(args, gadget, callback);
    };

    _services.basic.prototype.uniqueToken = function (args, gadget, callback) {
        Phx.AJAX.callproxy('Gadgets_CreateUniqueToken', function (responseData) {
            if (typeof callback === 'function') {
                callback(responseData.module.data.token);
            }
        },"",'','POST');
    };

    _services.basic.prototype.install = function (args, gadget, callback) {
        var newArgs = {0:'preview', 1:args[0]};
        this.requestNavigateTo(newArgs, gadget, callback);
    };

    /**
     * Service for Navigating to another view
     *
     * @param (String) requested View
     *
     * @return (void)
     */
    _services.basic.prototype.requestNavigateTo = function (args, gadget, callback) {
        var url;
        if((url = this._buildUrlForView(args[0], args[1], gadget))){
            if (url.type === 'popup') {
                var width = 602;
                var height = 413;
                if (args[3]) {
                    if (args[3].width) {
                        width = args[3].width;
                    }
                    if (args[3].height) {
                        height = args[3].height;
                    }
                }
                if (gadgets.sandbox) {
                    height += 77;
                    Phx.Application.Modules.popuplinks.openWindow(url.url, width, height);
                } else {
                    Phx.Application.Modules.popuplinks.openWindow(url.url, width, height);
                }
            } else {
                if (gadget.view === 'popup' || gadget.view === 'popupinstallation') {
                    var handle = window.opener;
                    document.domain.domain = handle.domain;
                    handle.window.location.href = url.url;
                    handle.focus();
                    if (url.close === true) {
                        window.close();
                    }
                } else {
                    window.location.href = url.url;
                }
            }
        } else {
            throw Error('UNSUPPORTED VIEW');
        }
    };

    /**
     * Implement view specific services here
     * ervery service inherits from the basic service
     */

    _services.canvas    = function (){
        this.maxHeight = 2000;
        _services.basic.call(this);

        this.setHeight = function (args, gadget, callback) {
            if(gadget.changeSize) {
                this.maxHeight = 2000;
            }
            if(args[0] < this.maxHeight) {
                $('#remote-iframe-' + gadget.mid).height(args[0]);
            } else {
                $('#remote-iframe-' + gadget.mid).height(this.maxHeight);
            }
        };
    };
    _services.canvas.inherits(_services.basic);

    _services.mobilecanvas    = function (){
        _services.basic.call(this);
    };
    _services.mobilecanvas.inherits(_services.basic);

    _services.groupcanvas    = function () {
        _services.canvas.call(this);
    };
    _services.groupcanvas.inherits(_services.canvas);

    _services.groupcanvasinstallation    = function (){
        _services.canvas.call(this);
    };
    _services.groupcanvasinstallation.inherits(_services.canvas);

    _services.group     = function (){
        this.maxHeight = 400;
        _services.basic.call(this);
    };
    _services.group.inherits(_services.basic);

    _services.groupinstallation    = function (){
        _services.basic.call(this);
    };
    _services.groupinstallation.inherits(_services.group);

    _services.popup = function (){
        this.maxHeight = 2000;

        this.setHeight = function (args, gadget, callback) {
            if(gadget.changeSize) {
                this.maxHeight = 2000;
            }
            if(args[0] < this.maxHeight) {
                $('#remote-iframe-' + gadget.mid).height(args[0]);
            } else {
                $('#remote-iframe-' + gadget.mid).height(this.maxHeight);
            }
        };
        
        _services.basic.call(this);
    };

    _services.popup.inherits(_services.basic);

    _services.popupinstallation    = function (){
        _services.popup.call(this);
    };
    _services.popupinstallation.inherits(_services.popup);

     _services.integration = function (){
        this.maxHeight = 60000;
        _services.basic.call(this);

        this.setHeight = function (args, gadget, callback) {
            if(gadget.changeSize) {
                this.maxHeight = 60000;
            }
            if(args[0] < this.maxHeight) {
                $('#remote-iframe-' + gadget.mid).height(args[0]);
            } else {
                $('#remote-iframe-' + gadget.mid).height(this.maxHeight);
            }
        };
    };

    _services.integration.inherits(_services.basic);

    _services.integrationinstallation    = function (){
        _services.basic.call(this);
    };
    _services.integrationinstallation.inherits(_services.integration);

    _services.preview = function (){
        this.maxHeight = 400;
        _services.basic.call(this);
    };

    _services.preview.inherits(_services.basic);

    _services.embedprovider = function (){
        this.maxHeight = 200;
        _services.basic.call(this);
    };

    _services.embedprovider.inherits(_services.basic);

    _services.embed = function (){
        this.maxHeight = 200;
        _services.basic.call(this);
    };

    _services.embed.inherits(_services.basic);

    _services.profile   = function (){
        this.maxHeight = 400;
        _services.basic.call(this);
    };
    _services.profile.inherits(_services.basic);

    _services.nobleprofile   = function (){
        this.maxHeight = 2000;
        _services.basic.call(this);

        this.setHeight = function (args, gadget, callback) {
            if(gadget.changeSize) {
                this.maxHeight = 2000;
            }
            if(args[0] < this.maxHeight) {
                $('#remote-iframe-' + gadget.mid).height(args[0]);
            } else {
                $('#remote-iframe-' + gadget.mid).height(this.maxHeight);
            }
        };
    };

    _services.nobleprofile.inherits(_services.basic);

    _services.nobleprofilecanvas    = function (){
        this.maxHeight = 2000;
        _services.basic.call(this);

        this.setHeight = function (args, gadget, callback) {
            if(gadget.changeSize) {
                this.maxHeight = 2000;
            }
            if(args[0] < this.maxHeight) {
                $('#remote-iframe-' + gadget.mid).height(args[0]);
            } else {
                $('#remote-iframe-' + gadget.mid).height(this.maxHeight);
            }
        };
    };
    _services.nobleprofilecanvas.inherits(_services.canvas);

//
//    _services.start     = function (){
//        _services.basic.call(this);
//    };
//    _services.start.inherits(_services.basic);


    _services.basic.prototype.postBadge = function (args, gadget, callback) {
        var userId = args[0].userId;
        if (userId === 'VIEWER') {
            userId = gadget.vw;
        } else if (userId === 'OWNER') {
            userId = gadget.o;
        }

        var a = args[0];
        var params = '&installationId=' + gadget.mid + '&gadgetId=' + gadget.aid
            + '&badgeUri=' + encodeURIComponent(a.badgeUri)
            + '&badgeTitle=' + encodeURIComponent(a.badgeTitle)
            + '&badgeDescription=' + encodeURIComponent(a.badgeDescription)
            + '&link=' + encodeURIComponent(a.link);
        Phx.Application.RequestRegistry.append({
            1: 'Badges_postBadge',
            2: function(response) {
                callback(response.module.data.badgeId);
            },
            3: '',
            4: params
        });
    };

    return {

        /**
         * get a service by view
         * !Service instances are Singletons!
         *
         * @param {String} view
         * @return (Object) instanceOf Basic Service
         */
        get : function (view) {
            if (_serviceRegistry[view]){
                return _serviceRegistry[view];
            } else {
                return (_serviceRegistry[view] = new _services[view]());
            }

        }

    };

};


/**
 * gadget Manager
 * returns the gadget data objects by iframeId
 *
 * @param {Object} gadgets
 *
 */
gadgets.gadgetManager = (function (gadgets) {

    /**
     * Gadget data objects
     * @var (Object)
     */
    var _gadgets = gadgets;

    /**
     * saves a prmitive map of iframe to gadget ids
     * prevents extracting the same id more than once
     */
    var _ifrToGidMap = {};

    /**
     * helper to extract the gadgetid from the given iframe id
     *
     * @param {String} frameId
     */
    var _getGid = function (frameId) {
        if(!_ifrToGidMap[frameId]) {
            _ifrToGidMap[frameId] = frameId.substring(frameId.lastIndexOf('-') + 1) || false;
        }
        return _ifrToGidMap[frameId];
    };


    return {
        /**
         * returns a gadget data object by id
         *
         *
         * @param {String} ifrId
         * @return (Object)
         */
        getGadgetById : function (ifrId) {
            if (isNaN(ifrId)) {
                if (ifrId.indexOf('remote') > -1) {
                    ifrId = 'inst' + _getGid(ifrId);
                }
                return _gadgets[ifrId]
            } else {
                return _gadgets['inst' + ifrId]
            }

        },

        setGadgetById : function (id, data) {
            _gadgets['inst' + id] = data;
        },

        setAllGadgets : function(gadgets) {
            _gadgets = gadgets;
        },

        /**
         *
         */
        getAllGadgets : function () {
           return _gadgets;
        },

        deleteGadgetById : function(id) {
            delete _gadgets['inst' + id];
        }
    };
// If gadget data store is changed it only has to be changed here
}(gadgets.data));

/**
 * @package
 */
gadgets.models = {};

/**
 * Main Models
 *
 * @static
 * @class Provides persistence methods
 * @name gadgets.models.main
 *
 */
gadgets.models.main = {

    /**
     * Save preferences for an installation
     * callback can be provided
     *
     * @param {Int} mid
     * @param {Object} prefs
     * @param {Funcition} optCb
     */
    savePreferences : function (mid, prefs, optCb) {
        var gadget = gadgets.gadgetManager.getGadgetById(mid);
        if (gadget.groupId) {
            var identifierParam = '&groupId=' + gadget.groupId;
        } else if (gadget.profileId) {
            var identifierParam = '&profileId=' + gadget.profileId;
        }else {
            var identifierParam = '';
        }
        var canvas = (gadget.view == 'canvas') ? 1 : 0;
        Phx.AJAX.callproxy('Gadgets_GadgetPrefs', function (responseData) {
            if(optCb) {
               optCb(responseData);
            }
            Phx.Application.Modules.gadgetscontroller.bindPrefsMenue(gadget.mid);
        },"",'&pref=' + prefs + '&installationId=' + mid + identifierParam + '&canvas=' + canvas,'POST');

    },

    /**
     * Uninstall a gadget by id
     *
     * @param {Int} id
     * @param {Bool} removeConsumerConnection
     */
    uninstallGadget : function (id, removeConsumerConnection) {

        var paramRemoveConsumerConnection = '';
        if (removeConsumerConnection) {
            paramRemoveConsumerConnection = '&removeConsumerConnection=1';
        }

        Phx.AJAX.callproxy('Gadgets_GadgetUninstall', Phx.Util.createDelegate(function(installId) {

            gadgets.gadgetManager.deleteGadgetById(installId);

            var myGallery = $('#MyGadgetGalleryContainer');
            if (myGallery.length === 0) {
                $('.gadgets-gadget-chrome').remove();
                return
            }
            $('#MyGadgetGalleryContainer').html('');
            $('.gadgets-gallerylist-item-' + installId).remove();
            
            Phx.Application.Modules.gadgetsmygallery.removeItem(installId);

            var counter = $('#Mod-Gadgets-MyGallery-Count');

            if (counter.length === 0) {
                return;
            }

            counter.html(parseInt(counter.html()) - 1);

        }, this, id),"",'&installationId='  + id + paramRemoveConsumerConnection, 'POST');
    },

    /**
     * serializes a form to an object
     * uses jquery serialize and splits result
     *
     * @param {String} selector
     */
    form2object : function (selector) {
        var serFor = $(selector).serialize();
        var serForArr = serFor.split('&');
        var helpObj = {};

        $.each(serForArr, function (i, data) {
            var parts = data.split('=');
            helpObj[parts[0]] = parts[1];
        });

        return helpObj;
    },

    /**
     * retrieves the vcard information
     *
     * @param {Int} gadgetId id of the gadget
     * @param {Function} callback function
     */
    getVcard : function (gadgetId, fn) {
        Phx.AJAX.callproxy('Gadgets_getVcardInformation', function(responseData) {fn(responseData);},"",'&gadgetId=' + gadgetId, 'POST');
    },

    /**
     * loads the suggest dialog
     *
     * @param {object} gadget gadget object
     * @param {object} additionalParams additional url parameters
     */
    getSuggestDialog : function(gadget, additionalParams) {
        var urlParams = {};
        var additionalUrlParams = additionalParams || {};

        if (! gadgets.sandbox) {
            if (gadget.groupId) {
                urlParams.type = 'GroupGadget';
                urlParams.id   = gadget.groupId;
            } else if (gadget.profileId) {
                urlParams.type = 'Gadget';
                urlParams.id   = gadget.profileId;
            } else {
                return;
            }
        } else {
            urlParams.sandbox = '1';
            urlParams.gadgetRevisionId = gadget.v;
        }

        urlParams.gadgetInstallation = gadget.mid;
        urlParams.gadgetId = gadget.aid;
        urlParams = '&' + Phx.Util.encodeValues(urlParams);
        if (additionalParams) {    
            urlParams += '&' + additionalUrlParams;
        }

        Phx.Application.RequestRegistry.append({
            1:  'Gadgets_getSuggestForm',
            2:  function(response) {
                    var _htmlDialog = Phx.UI.Dialog.HTML(i18n.getText('link_head'), {
                        message : '<div id="Mod-Suggest2" class="obj-box">' + response.module.data.html + '</div>'
                    });

                    _htmlDialog.show();

                    // init the link form
                    Phx.Application.Modules.LinkForm.init();
                },
            3:  '',
            4:  urlParams
        });
    },

    /**
     * loads the uninstall dialog
     *
     * @param integer gadget installationId
     * @return void
     */
    getUninstallDialog : function(installationId) {
        Phx.Application.RequestRegistry.append({
            1:  'Gadgets_uninstallDialog',
            2:  function(response) {

                    if (response.module.data.error) {
                        return;
                    }

                    var _htmlDialog = Phx.UI.Dialog.HTML(i18n.getText('gadgets_uninstall_title'), {
                        message : response.module.data.html
                    });

                    _htmlDialog.show();
                    $('#link-gadget-delete-submit').unbind('click.uninstall').bind('click.uninstall', function() {
                        var removeConsumerConnection = true;
                        if ($('#remove-consumer-connection').length > 0) {
                            removeConsumerConnection = $('#remove-consumer-connection')[0].checked;
                        }
                        gadgets.models.main.uninstallGadget(installationId, removeConsumerConnection);
                        _htmlDialog.close();
                    });
                },
            3:  '',
            4:  '&installationId=' + installationId
        });
    }
}

gadgets.view = function () {

    /**
     * toggles preferences form visibility
     *
     * @param {Int} id
     */
    this.togglePrefVisibility = function (id) {
        if($('#gadgets-gadget-prefs-' + id).is(':visible')) {
            $('#gadgets-gadget-prefs-' + id).hide();
            $('#gadgets-gadget-title-bar-' + id).show();
        } else {
            $('#gadgets-gadget-prefs-' + id).show();
            $('#gadgets-gadget-settings-' + id).hide();
            $('#gadgets-gadget-title-bar-' + id).hide();
        }

    };

    /**
     * toggles settings form visibility
     *
     * @param {Int} id
     */
    this.toggleSettingsVisibility = function (id) {
        if($('#gadgets-gadget-settings-' + id).is(':visible')) {
            $('#gadgets-gadget-settings-' + id).hide();
            $('#gadgets-gadget-title-bar-' + id).show();
        } else {
            $('#gadgets-gadget-settings-' + id).show();
            $('#gadgets-gadget-prefs-' + id).hide();
            $('#gadgets-gadget-title-bar-' + id).hide();
        }
    };

    /**
     * Toggles the visibility of the whole gadget
     *
     * @param {Int} id
     */
    this.toggleGadgetVisibility = function (id) {
        if($('#gadgets-gadget-content-' + id).is(':visible')) {
            $('#gadgets-gadget-content-' + id).addClass('hidden');
            this.toggleMinMaxIcon(id, true);
        } else {
            $('#gadgets-gadget-content-' + id).removeClass('hidden');
            this.toggleMinMaxIcon(id, false);
        }
    };

    this.toggleMinMaxIcon = function (id, collapse) {
        if(collapse) {
            $('#gadget-collapse-' + id).attr('class','window-controls-expand');
        } else {
            $('#gadget-collapse-' + id).attr('class','window-controls-collapse');
        }
    };
}


/**
 * Gadget Controller
 *
 * self executing on app startup, registration of rpc services is done here
 * handles the the provided services for the different views
 *
 */
Phx.namespace('Phx.Application.Modules.gadgetscontroller', new function () {

        /**
         * gadgets view instance
         *
         * @var object
         */
        var _view = new gadgets.view();

        /**
         * Factory for the services
         * should be used to get the rpc functionality for a view
         *
         * @var object
         */
        var ifrRemoteServiceFactory = new gadgets.remoteServiceFactory();

        /**
         * safe proxy
         * verifying whether a gadget may use the requested service or not
         *
         * @param {String} serviceName
         * @param {Array}  args
         * @param {Object} con
         *
         * @return (void)
         */
        var _proxy = function (serviceName, args, con) {
            var gadget = gadgets.gadgetManager.getGadgetById(con.f);
            var remoteService = ifrRemoteServiceFactory.get(gadget.view);
            if ('function' === typeof remoteService[serviceName]) {
                var r = remoteService[serviceName](args, gadget, con.callback);
            }
        };

        /**
         * startup routine - generating the gadget iframes
         *
         * @return (void)
         */
        this.generateGadgets = function () {
            var gadgets_ = gadgets.gadgetManager.getAllGadgets();
            for (var i in gadgets_) {
                if (gadgets_[i].generated) {
                    continue;
                }
                gadgets_[i].generated = true;
                //if viewer equals owner parse preferences for later editing
                if (gadgets_[i].viewer === gadgets_[i].owner) {
                    gadgets_[i].prefs = gadgets.models.main.form2object('#gadgets-gadget-prefs-' + gadgets_[i].mid + ' form');
                }

               _bindViewTracking(gadgets_[i]);

                gadgets.rpc.setAuthToken('remote-iframe-' + gadgets_[i].mid, gadgets.rpctoken);
                gadgets.rpc.setRelayUrl('remote-iframe-' + gadgets_[i].mid, gadgets.shindigUrl + '/gadgets/files/container/rpc_relay.html', false);
                $('<iframe ' + gadgets_[i].frameParams + ' src="about:blank" />').appendTo('#gadgets-gadget-content-' + gadgets_[i].mid);
                var iframe = document.getElementById('remote-iframe-' + gadgets_[i].mid);
                iframe.contentWindow.location.replace(gadgets_[i].iframeUrl + '&rpctoken=' + gadgets.rpctoken);
            }
        };

        var _bindViewTracking = function(gadget) {
            if (gadgets.sandbox) {
                return;
            }

            switch (gadget.view) {
                case 'canvas':
                case 'embedprovider':
                case 'popup':
                case 'popupinstallation':
                case 'integration':
                case 'integrationinstallation':
                case 'nobleprofilecanvas':
                case 'groupcanvas':
                case 'groupcanvasinstallation':
                    Phx.Application.Modules.gadgetscontroller.trackGadgetView(gadget);
                    break;
                case 'group':
                    $('#gadgets-gadget-content-' + gadget.mid).unbind('mouseover').bind('mouseover', function() {
                        $(this).unbind('mouseover');
                        window.setTimeout(function() {
                            if (typeof(gadgets.gadgetManager.getGadgetById(gadget.mid)) !== "undefined") {
                                Phx.Application.Modules.gadgetscontroller.trackGadgetView(gadget);
                            }
                        }, 10 * 1000);
                    });
                    break;
                case 'profile':
                    if (gadget.viewer === gadget.owner) {
                        $('#gadgets-gadget-content-' + gadget.mid).unbind('mouseover').bind('mouseover', function() {
                            $(this).unbind('mouseover');
                            window.setTimeout(function() {
                                if (typeof(gadgets.gadgetManager.getGadgetById(gadget.mid)) !== "undefined") {
                                    Phx.Application.Modules.gadgetscontroller.trackGadgetView(gadget);
                                }
                            }, 10 * 1000);
                        });
                    }
                    break;
                default:
                    break;
            }
        };

        var _bindFeaturedGadget = function () {
            var gadget = $('#Mod-Gadgets-Overview-Featured-One .gadgets-gadget-chrome');
            if (gadget.length === 0) {
                return;
            }
            gadget.unbind('click').bind('click', function(event) {
               Phx.Event.stop(event);
               var link = $('#Mod-Gadgets-Overview-Featured-One a');
               if (link.length === 0) {
                   return;
               }
               window.location.href = link.attr('href');
            });
        };

        /**
         * binds all gui events
         *
         * @return (void)
         */
         this.bindGui = function () {

            var gadgets_ = gadgets.gadgetManager.getAllGadgets();
            for (var i in gadgets_) {
                var installationId = gadgets_[i].mid;

                this.bindPrefsMenue(installationId);

                this.bindVcardInformation(gadgets_[i]);

                this.bindNavigationLinks(gadgets_[i]);
                
                this.bindSuggestLink(gadgets_[i]);
                
                //do not bind install/uninstall buttons when in sandbox
                if (gadgets.sandbox) {
                    $('#gadgets-gadget-install-' + gadgets_[i].mid).unbind('click').bind('click', function(event){Phx.Event.stop(event);});
                    $('#gadgets-gadget-uninstall-' + gadgets_[i].mid).unbind('click').bind('click',function(event){Phx.Event.stop(event);});
                    continue;
                }

                $('#gadgets-gadget-uninstall-' + gadgets_[i].mid).unbind('click').bind('click',  Phx.Util.createDelegate(
                    function (installationId, event) {
                        Phx.Event.stop(event);

                        gadgets.models.main.getUninstallDialog(installationId);
                        
                    }, this, installationId)
                );
            }
        };

        this.bindNavigationLinks = function (gadget) {
            var remoteService = ifrRemoteServiceFactory.get(gadget.view);
            var navigationLink = $('#gadget-navigation-' + gadget.mid);
            if (navigationLink.length === 0) {
                return;
            }
            var url = remoteService['_buildUrlForView'](navigationLink.attr('name'), gadget['view-params'], gadget);
            navigationLink.attr('href', url.url);
            navigationLink.unbind('click').bind('click', Phx.Util.createDelegate(function(gadget) {
                remoteService['requestNavigateTo']([navigationLink.attr('name'), gadget['view-params']], gadget, null);
            }, this, gadget));
        }

        /**
         * bind vcard information overlay
         */
        this.bindVcardInformation = bindVcardInformation;
        
        function bindVcardInformation(gadget) {
            $('#gadget-vcard-link-' + gadget.mid).unbind('click').bind('click', Phx.Util.createDelegate(function(gadget) {
                $('#gadget-vcard-link-' + gadget.mid).unbind('click');
                gadgets.models.main.getVcard(gadget.aid, function(responseData) {
                    _dialog = Phx.UI.Dialog.HTML(i18n.getPText('vcard_dialog_headline'), {
                        message : responseData.module.data.html
                    });

                    _dialog.show();
                    bindVcardInformation(gadget);            
                    Phx.Application.Modules.Accordion.init();

                    $('#Vcard-Information-Close-Link').unbind('click').bind('click', function() {
                        _dialog.close();
                    });
                });
            }, this, gadget));
        }

        /**
         *
         */
        this.bindPrefsMenue = function (i) {
               $('#gadgets-gadget-prefs-' + i + ' input[name=submit]').unbind('click').bind('click' , Phx.Util.createDelegate(
                    function (installId, event ) {
                        event.preventDefault();
                        Phx.Event.stop(event);

                        var helpObj = gadgets.models.main.form2object('#gadgets-gadget-prefs-' + i + ' form');
                        gadgets.models.main.savePreferences(installId, JSON.stringify(helpObj), function(responseData) {
                            var myGadget=gadgets.gadgetManager.getGadgetById(responseData.module.data.gadget.mid);
                            $('#remote-iframe-' + responseData.module.data.gadget.mid).attr({'src': responseData.module.data.gadget.iframeUrl + '&view-params=' + myGadget['view-params'] + '&rpctoken=' + gadgets.rpctoken});
                        });
                    }, this, i)
                );

                $('#gadgets-gadget-prefs-' + i + ' .form-buttons a').unbind('click').bind('click' , Phx.Util.createDelegate(
                    function (installId) {
                        _view.togglePrefVisibility(installId);
                    }, this, i)
                );

                $('#settings-gadget-' + i).unbind('click').bind('click', Phx.Util.createDelegate(
                    function (installId) {
                        _view.toggleSettingsVisibility(installId);
                    }, this, i)
                );

                $('#prefs-gadget-' + i).unbind('click').bind('click', Phx.Util.createDelegate(
                    function (installId) {
                        _view.togglePrefVisibility(installId);
                    }, this, i)
                );
        };

        this.bindSuggestLink = function(gadget) {
            $('#tell-gadget-' + gadget.mid).unbind('click').bind('click', function(event) {
                Phx.Event.stop(event);
                gadgets.models.main.getSuggestDialog(gadget);
            });
        };

        var updated = false;

        var _updateSecurityToken = function() {
            updated = false;
            var gadgets_ = gadgets.gadgetManager.getAllGadgets();
            if (typeof(Phx.Application.Modules.Chat) !== 'undefined' && Phx.Application.Modules.Chat != null
               && typeof(Phx.Application.Modules.Chat.CommunicationService) !== 'undefined' && Phx.Application.Modules.Chat.CommunicationService != null) {
                Phx.Application.Modules.Chat.CommunicationService.triggerUserInteraction();
            }
            for (var i in gadgets_) {
                var sandbox = '0';
                if (gadgets.sandbox) {
                    sandbox = '1';
                }
                Phx.AJAX.callproxy('Gadgets_GetSecurityToken', function (responseData) {
                    gadgets_[responseData.module.data.installation].st = responseData.module.data.st;
                    gadgets.rpc.call('remote-iframe-' + gadgets_[responseData.module.data.installation].mid, "update_security_token", null, responseData.module.data.st);
                    if (updated === false) {
                        updated = true;
                        Phx.Application.Modules.gadgetscontroller.initSecurityTokenUpdate();
                    }
                },"",'&installation=' + i + '&gadgetRevision=' + gadgets_[i].v + '&sandbox=' + sandbox + '&st=' + encodeURIComponent(gadgets_[i].st),'POST');
            }
        };

        this.initSecurityTokenUpdate = function () {
           window.setTimeout(_updateSecurityToken, 5 * 60 * 1000);
        };

        this.initPubSub = function() {
            gadgets.pubsubrouter.init(function(id) {
                var pubsubGadget = gadgets.gadgetManager.getGadgetById(id);
                return pubsubGadget['iframeUrl'];
            }, {
                onSubscribe: function(sender, channel) {
                  // return true to reject the request.
                  return false;
                },
                onUnsubscribe: function(sender, channel) {
                  // return true to reject the request.
                  return false;
                },
                onPublish: function(sender, channel, message) {
                  // return true to reject the request.
                  return false;
                }
            });
        };

        this.trackGadgetView = function(gadget) {
            if (gadgets.sandbox || window.location.host.indexOf('svz-pc') > 0) {
                return;
            }
//            Phx.Util.createDelegate(function() {
//                var script = document.createElement('script');
//                document.body.appendChild(script);
//                script.onload = function(script){
//                    try {
//                        document.body.removeChild(script);
//                    } catch (e){}
//                };
//
//                var host = window.location.host.replace('www.', '');
//                var url = "http://t." + host + "/view?";
//
//                url += 't=' + (new Date()).valueOf();
//                url += '&aid=' + gadget.aid;
//                url += '&userid=' + gadget.viewer;
//                url += '&view=' + gadget.view;
//                try {
//                    script.src = url;
//                } catch(e) {}
//            }, null)();
            
            var host = window.location.host.replace('www.', '');
            var url = "http://t." + host + "/view?";

            url += 't=' + (new Date()).valueOf();
            url += '&aid=' + gadget.aid;
            url += '&userid=' + gadget.viewer;
            url += '&view=' + gadget.view;
            url += '&efr=' + gadget.profileId;

            Phx.Util.getScriptAsync(url);   
        }
        var handleOsapiGadgetRpcMethod = function(requests) {
            var responses = new Array(requests.length);
            var callCount = 0;
            var callback = this.callback;
            var dummy = function(params, apiCallback) {
              apiCallback({});
            };
            for (var i = 0; i < requests.length; i++) {
              // Don't allow underscores in any part of the method name as a convention
              // for restricted methods
              var current = osapi;
              if (requests[i].method.indexOf('_') == -1) {
                var path = requests[i].method.split('.');
                for (var j = 0; j < path.length; j++) {
                  if (current.hasOwnProperty(path[j])) {
                    current = current[path[j]];
                  } else {
                    // No matching api
                    current = dummy;
                    break;
                  }
                }
              } else {
                current = dummy;
              }

              // Execute the call and latch the rpc callback until all
              // complete
              current(requests[i].params, function(i) {
                return function(response) {
                  // Put back in json-rpc format
                  responses[i] = { id: requests[i].id, data: response};
                  callCount++;
                  if (callCount == requests.length) {
                    callback(responses);
                  }
                };
              }(i));
            }
        }
        this.init = function() {
            
            if (!gadgets || !gadgets.rpc) {
                return;
            }
            /**
             * Constructor stuff
             *
             * register all available rpc calls here and implement them in the views
             */
            gadgets.rpc.register('resize_oembediframe', function (height, width) {
                var iframeId = '#oembed-ifr-' + parseInt(this.f);
                $(iframeId).attr('height', parseInt(height));
                if (width !== null) {
                    $(iframeId).attr('width', parseInt(width));
                }
            });
            gadgets.rpc.register('resize_iframe',       function () {
                _proxy('setHeight', arguments, this);
            });
            gadgets.rpc.register('set_pref',            function () {
                _proxy('setPref', arguments, this);
            });
            gadgets.rpc.register('set_title',            function () {
                _proxy('setTitle', arguments, this);
            });
            gadgets.rpc.register('requestNavigateTo',    function () {
                _proxy('requestNavigateTo', arguments, this);
            });
            gadgets.rpc.register('invite',    function () {
                _proxy('invite', arguments, this);
            });
            gadgets.rpc.register('uniqueToken',    function () {
                _proxy('uniqueToken', arguments, this);
            });
            gadgets.rpc.register('install',    function () {
                _proxy('install', arguments, this);
            });
            gadgets.rpc.register('suggest',    function () {
                _proxy('suggest', arguments, this);
            });
            gadgets.rpc.register('updateVcard',    function () {
                _proxy('updateVcard', arguments, this);
            });
            gadgets.rpc.register('getAdTag',    function () {
                _proxy('getAdTag', arguments, this);
            });
            gadgets.rpc.register('sendEmbed',    function () {
                _proxy('sendEmbed', arguments, this);
            });
            gadgets.rpc.register('sendPrivateMessage',    function () {
                _proxy('sendPrivateMessage', arguments, this);
            });
            gadgets.rpc.register('sendPublicMessage',    function () {
                _proxy('sendPublicMessage', arguments, this);
            });
            gadgets.rpc.register('getEmbedUrl',    function () {
                _proxy('getEmbedUrl', arguments, this);
            });
            gadgets.rpc.register('getStaticContentUrl',    function () {
                _proxy('getStaticContentUrl', arguments, this);
            });
            gadgets.rpc.register('getStaticContent',    function () {
                _proxy('getStaticContent', arguments, this);
            });
            gadgets.rpc.register('getPaymentInterstitial', function() {
                _proxy('showPaymentInterstitial', arguments, this);
            });
            gadgets.rpc.register('writeFeedEntry', function() {
                _proxy('writeFeedEntry', arguments, this);
            });
            gadgets.rpc.register('getPermissions', function() {
                _proxy('getPermissions', arguments, this);
            });
            gadgets.rpc.register('postBadge', function() {
                _proxy('postBadge', arguments, this);
            });
            gadgets.rpc.register('updatePerson', function() {
                _proxy('updatePerson', arguments, this);
            });
            
            gadgets.rpc.register('osapi._handleGadgetRpcMethod', handleOsapiGadgetRpcMethod);

            this.generateGadgets();

            this.bindGui();
            _bindFeaturedGadget();

            this.bindPrefsMenue();

            this.initSecurityTokenUpdate();

            this.initPubSub();

        }
}());

