var MD5 = new MD5();

var Mplus = {
    switchUser: null,
	login: null,

    remote: function(sendObj, callback, authenticate, hint, proxy) {
        this.login = $E(".widget_login");
		if(!this.login.widget) {
			// we're in a hacky pre-load state (likely webadmin is involved)
			this.remote.delay(100, this, [sendObj, callback, authenticate,
										  hint, proxy]);
			return;
		}
		this.login = this.login.widget;
		var that = this;
        var authObj = {};
		if(!$defined(this.login.expires)) {
			this.login.expires = 0;
		}
        var timeleft = this.login.expires - $time();
        var call = [];
		var fullCall = "";
        var key = null;
		if(!this.login.loginKey) {
			// allow some old (and abusive) code to work
			// in this new world order of multiple auth sources
			this.login.loginKey = "mplus.directory.login";
		}
		if(this.login.loginObj) {
			key = this.login.loginObj[this.login.loginKey].key;
		}

        authenticate = authenticate || false;
        hint = hint || null;

        if(!key || authenticate || timeleft < 1000) {
            call = [this.login.loginKey];
            if(hint) {
                call.push(":", hint);
            }
			fullCall = call.join("");
            authObj = {};

            if(this.login.pass && this.login.pass.length > 0) {
                authObj[fullCall] = {
                    "user": this.login.user,
                    "pass": this.login.pass,
                    "authenticate": authenticate
                };
            } else {
                authObj[fullCall] = {
                    "authenticate": authenticate
                };
            }
        } else {
            call = ["mplus.directory.resume"];
            if(hint) {
                call.push(":", hint);
            }
			fullCall = call.join("");
            authObj = {};
            authObj[fullCall] = {
                "object": this.login.loginObj["mplus.directory.login"].object,
                "pass": MD5.hex_md5(key + timeleft.toString()),
                "remainder": timeleft
            };
        }
        if(Mplus.switchUser) {
            authObj["mplus.directory.switch"] = Mplus.switchUser;
        }

        // make sure login/resume succeeded before doing the callback
        var verify = function(res) {
//			var login = $E(".widget_login").widget;
			var login = that.login;
			if(!res[fullCall]) {
				alert(fullCall + "\n not in: \n" + Json.toString(res));
			}
            if(call[0] == "mplus.directory.resume") {
                if(res[fullCall].error) {
                    // resume failed, fall back on login
                    login.expires = 0;
                    login.key = null;
                    return Mplus.remote(sendObj, callback, authenticate, hint);
                }
            } else if(call[0] == that.login.loginKey) {
                if(res[fullCall].error) {
                    // login failed altogether, kick the user out
                    window.location.href = window.location.href;
                    return;
                } else {
                    // success, update the expiration
                    var timeout = res[fullCall].timeout;
                    var key = res[fullCall].key;
                    login.expires = timeout + $time();
                    login.key = key;
                }
            }
            // all is well, hand off to the callback
            callback(res);
        };
		var path = "/authenticated/handleajaj";
		if(proxy) {
			path = "/mplus-cluster/" + proxy + "/authenticated/handleajaj";
		}
        return Warp.remote($merge(authObj, sendObj), verify, path);
    }
};

