/**
 * All content on this website (including text, images, source
 * code and any other original works), unless otherwise noted,
 * is licensed under a Creative Commons License.
 * 
 * http://creativecommons.org/licenses/by-nc-sa/2.5/
 * 
 * Copyright (C) Open-Xchange Inc., 2011
 * Mail: info@open-xchange.com
 * 
 * @author Viktor Pracht <viktor.pracht@open-xchange.com>
 * 
 */

function hookDeferred(deferred, callback) {
    var done = deferred.done;
    deferred.done = function() {
        deferred.done = done;
        callback();
        return done.apply(this, arguments);
    };
}

var OAuthAccounts = new jQuery.Deferred();
hookDeferred(OAuthAccounts, function() {
    ox.JSON.get(AjaxRoot + "/oauth/accounts?action=all&session=" + session,
        function(reply) { OAuthAccounts.resolve(reply.data); });
});

/**
 * Creates a new OAuth account.
 * @param {Object} data The account description with either the field id or
 * serviceId and displayName.
 * @param {Function} callback A callback function which is called with the data
 * of the new account, if the authorization was successful.
 */
function createOAuthAccount(data, callback) {
    var params = "id" in data ? "id=" + encodeURIComponent(data.id)
        : "serviceId=" + encodeURIComponent(data.serviceId) +
          "&displayName=" + encodeURIComponent(data.displayName);
    var action = "id" in data ? "callback_reauthorize" : "callback_create";
    ox.JSON.get(AjaxRoot + "/oauth/accounts?action=init&" + params +
        "&session=" + session,
        function(reply) {
            var oldHandler, hasOldHandler = action in window;
            if (hasOldHandler) oldHandler = window[action];
            window[action] = function(reply) {
                win.close();
                if (hasOldHandler) {
                    window[action] = oldHandler;
                } else {
                    delete window[action];
                }
                if (!("id" in data)) {
                    OAuthAccounts.then(function(accounts) {
                        accounts.push(reply.data);
                        callback(reply.data);
                    });
                }
            };
            var win = window.open(reply.data.authUrl);
        });
}

if (requireOAuth.required) enableOAuth(); else requireOAuth = enableOAuth;

register("OX_Configuration_Loaded_Complete", function() {
    var messaging = configGetKey("modules.messaging");
    if (   messaging
        && !(typeof messaging == "object" && messaging.module === false))
    {
        requireOAuth();
    }
});

function enableOAuth() {
    requireOAuth = emptyFunction;
    new ox.Configuration.InnerNode("configuration/oxsocial",
        _("My Social Configuration"));
    var node = new ox.Configuration.LeafNode("configuration/oxsocial/oauth", 
        _("Accounts"));
    var split = new ox.Configuration.VSplit(node, _("OAuth Accounts"), 0.28);
    
    var services = new jQuery.Deferred();
    hookDeferred(services, function() {
        ox.JSON.get(AjaxRoot + "/oauth/services?action=all&session=" + session,
            function(reply) {
                var map = {};
                for (var i = 0; i < reply.data.length; i++) {
                    var service = reply.data[i];
                    map[service.id] = service.displayName;
                }
                services.resolve(map, reply.data);
            });
    });
    
    var grid, selection;
    split.init = function() {
        selection = new Selection();
        grid = new LiveGrid([{
            text: _("Service"),
            index: "serviceId",
            id: "serviceId",
            sortable: true,
            clear: LiveGrid.makeClear(""),
            set: function(div, serviceId) {
                services.then(function(map) {
                    LiveGrid.defaultSet(div, map[serviceId]);
                });
            }
        }, {
            text: _("Account name"),
            index: "displayName",
            id: "displayName",
            sortable: true,
            clear: LiveGrid.makeClear(""),
            set: LiveGrid.defaultSet
        }], selection);
        grid.sort = LiveGrid.localSort;
        grid.emptylivegridtext = _("No accounts created");
        split.list = grid;
        split.enableList = enableList;
        split.load = load;
        split.save = save;
        split.onNew = onNew;
        split.toolbar = temporary.configuration.newToolbar(_("OAuth Accounts"),
            [temporary.configuration.saveButton, {
                title: _("OAuth Accounts"),
                buttons: [{
                    title: _("Add"),
                    icons: ["img/menu/add_category.gif",
                            "img/menu/add_category_d.gif"],
                    action: function() { split.onNew(); }
                }, {
                    title: _("Delete"),
                    icons: ["img/menu/delete.gif", "img/menu/delete_d.gif"],
                    action: confirmDelete
                }]
            }]);
        
        var servicesCB = new ox.UI.ComboBox(_("Service"));
        services.then(function(map, array) {
            var ids = [], names = [];
            for (var i = 0; i < array.length; i++) {
                ids.push(array[i].id);
                names.push(noI18n(array[i].displayName));
            }
            servicesCB.setEntries(ids, names);
        });
        split.addWidget(servicesCB, {
            get: function(data, value) { data.serviceId = value; },
            set: function(data) {
                servicesCB.setEnabled(split.isNew);
                return data.serviceId;
            }
        });
        split.addWidget(new ox.UI.Input(_("Name")), "displayName");
        var text1 = new ox.UI.Text(format(
            //#. %s is the product name (default 'Open-Xchange Server')
            _("You need to authorize %1$s to use your account. Please click on the button below and the authorization will proceed in a separate window."),
            oxProductInfo.product_name));
        split.addWidget(text1, {
            get: emptyFunction,
            set: function(data) { text1.setVisible(split.isNew); }
        });
        var text2 = new ox.UI.Text(format(
            _("If the authorization expired or was revoked, you can repeat the authorization process by clicking on the button below. The authorization will proceed in a separate window."),
            oxProductInfo.product_name));
        split.addWidget(text2, {
            get: emptyFunction,
            set: function(data) { text2.setVisible(!split.isNew); }
        });
        var authorize = new ox.UI.Button(_("Authorize"));
        authorize.click = authorizeClick;
        split.addWidget(authorize);
    };
    
    var storage = new Storage(0, [], 0, 0, 0, 0,
        function(account) { return account.id; });
    function enableList() {
        ox.JSON.get(AjaxRoot + "/oauth/accounts?action=all&session=" + session,
            function(reply) {
                storage.remove(0, storage.ids.length);
                storage.append(reply.data);
                grid.enable(storage);
                grid.setSort(grid.sort_id, grid.sort_order);
                if (!reply.data.length) split.onNew();
                if (OAuthAccounts.isResolved()) {
                    OAuthAccounts.then(function(accounts) {
                        accounts.length = reply.data.length;
                        for (var i = 0; i < reply.data.length; i++) {
                            accounts[i] = reply.data[i];
                        }
                    });
                } else {
                    OAuthAccounts.resolve(reply.data);
                }
            });
    }
    
    function load(cont) {
        storage.newIterate(selection.getSelected(), emptyFunction,
            function(i, data) { cont(data); });
    }
    
    function save(data, cont) {
        ox.JSON.put(AjaxRoot + "/oauth/accounts?action=update&id=" + data.id +
            "&session=" + session, { displayName: data.displayName },
            function(reply) {
                storage.localUpdate([data.id], function(i, old) {
                    old.displayName = data.displayName;
                    return old;
                });
                cont(data);
                
            });
    }
    
    function onNew() { split.addNew({}); }
    
    function authorizeClick() {
        var data = split.get();
        createOAuthAccount(split.isNew ? { serviceId: split.children[0].get(),
                                           displayName: data.displayName }
                                       : { id: split.id },
            function(data) {
                storage.append([data]);
                split.set(data);
                split.original = split.get();
            });
    }

    function confirmDelete() {
        var count = split.list.selection.count;
        if (!count) return;
        newConfirm(
            ngettext("Delete account", "Delete accounts", count),
            ngettext("Are you sure you want to delete the selected account?",
                "Are you sure you want to delete the selected accounts?",
                count),
            AlertPopup.YES | AlertPopup.NO, null, null, handleDelete);
    }

    function handleDelete() {
        var ids = split.list.selection.getSelected();
        var request = new Array(ids.length);
        for (var i = 0; i < ids.length; i++) {
            request[i] = { module: "oauth/accounts", action: "delete",
                           id: ids[i] };
        }
        ox.JSON.put(AjaxRoot + "/multiple?continue=true&session=" + session, request,
            function(reply) {
                var deleted = [];
                for (var i = 0; i < reply.length; i++) {
                    if (reply[i].error) {
                        newServerError(reply[i]);
                    } else {
                        deleted.push(ids[i]);
                    }
                }
                if (deleted.length) {
                    split.list.deleteIDs(deleted);
                    OAuthAccounts.then(function(accounts) {
                        for (var i = 0; i < deleted.length; i++) {
                            for (var j = 0; j < accounts.length; j++) {
                                if (deleted[i] == accounts[j].id) {
                                    accounts = accounts.splice(j, 1);
                                    break;
                                }
                            }
                        }
                    });
                }
            });
    }
}
