/* jquery provides no mechanism for encoding JSON on browsers without native support */
var JSON = JSON || {};

JSON.stringify = JSON.stringify || function (obj) {
    var t = typeof (obj);
    if (t != "object" || obj === null) {
        // simple data type
        if (t == "string") {
			obj = '"' + obj + '"';
		}
        return String(obj);
    }
    else {
        // recurse array or object
        var n, v, json = [], arr = (obj && obj.constructor == Array);
        for (n in obj) {
            v = obj[n]; t = typeof(v);
            if (t == "string") {
				v = '"' + v + '"';
			}
            else if (t == "object" && v !== null) {
				v = JSON.stringify(v);
			}
            json.push((arr ? "" : '"' + n + '":') + String(v));
        }
        return (arr ? "[" : "{") + String(json) + (arr ? "]" : "}");
    }
};

/* add the ability to serialize a form as an associative array */
jQuery.fn.extend({
	serializeHash: function () {
		var hash = {};
		var a = this.serializeArray();
		var l = a.length;
		for (var i=0; i<l; i++) {
			var e = a[i];
			if (hash[e.name]) {
				if (! jQuery.isArray(hash[e.name])) {
					hash[e.name] = [hash[e.name]];
				}
				hash[e.name].push(e.value);
			}
			else {
				hash[e.name] = e.value;
			}
		}
		return hash;
	}
});

/* jquery inexplicably has a getJSON shortcut, but not a postJSON one */
$.postJSON = function(url, data, callback) {
	$.ajax({
		type: 'POST',
		url: url,
		data: JSON.stringify(data),
		success: callback,
		dataType: 'json',
		contentType: 'application/json'
	});
};

/* we don't want arrays serialized with [] appended to the key names */
jQuery.ajaxSettings.traditional = true;

var LW       = LW || {};
LW.vars = LW.vars || {};
LW.JSON = {
	_redo: [],
	preLoad: function (url, data, callback, before, timeout) {
		LW.JSON.cache.set(url, data, timeout);
		if (before) {
			before();
		}
		if (! LW.JSON.handleError(data)) {
			callback(data);
		}
	},
	load: function (url, callback, before, timeout, onError) {
		var data = LW.JSON.cache.get(url);
		if (data) {
			if (before) {
				before();
			}
			callback(data);
			return;
		}

		if (LW.JSON.cache.isReserved(url)) {
			return;
		}

		var method = arguments.callee.caller;
		var arg    = method.arguments[0];
		LW.JSON._redo.push([ url, callback, before, timeout ]);

		LW.JSON.cache.reserve(url);
		if (before) {
			before();
		}
		$.getJSON(url, function (response) {
			LW.JSON.cache.cancelReservation(url);
			var fail = false;
			if (onError) {
				fail = onError(response);
			}
			else {
				fail = LW.JSON.handleError(response);
			}

			if (! fail) {
				LW.JSON.cache.set(url, response, timeout);
				callback(response);
			}
			if (! LW.vars.loggedOut) {
				LW.JSON._redo = [];
			}
		});
	},
	cache: {
		_cache: {},
		_reserved: {},
		_timeout: {},
		reserve: function (url) {
			LW.JSON.cache._reserved[url] = true;
		},
		isReserved: function (url) {
			return LW.JSON.cache._reserved[url];
		},
		cancelReservation: function (url) {
			LW.JSON.cache._reserved[url] = false;
		},
		set: function (url, data, timeout) {
			/* default the timeout to 2 minutes */
			timeout = timeout || 120;

			LW.JSON.cache.cancelReservation(url);
			LW.JSON.cache._timeout[url] = setTimeout(function () {
				LW.JSON.cache.expire(url);
			}, timeout * 1000);

			LW.JSON.cache._cache[url] = data;
		},
		get: function (url) {
			return LW.JSON.cache._cache[url];
		},
		expire: function (url) {
			LW.JSON.cache._cache[url] = null;
			LW.JSON.cache.cancelReservation(url);
			if (LW.JSON.cache._timeout[url]) {
				clearTimeout(LW.JSON.cache._timeout[url]);
			}
		}
	},
	handleError: function (response) {
		if (! response) {
			/* call was aborted, don't throw a js error */
			return true;
		}

		if (! response.error_class) {
			return false;
		}
		var type = response.error_class;

		if (type == 'LW::Exception::RemoteService::Authorization') {
			/* their login has timed out, show the login prompt */
			if (! LW.vars.loggedOut) {
				LW.DHTML.popupLogin();
			}
		}
		else if (type == 'LW::Exception::RecordNotFound' && response.field == 'subaccnt') {
			/* the server no longer exists, but we don't know the uniq_id at this point */
			response.server_went_away = true;
			return false;
		}
		else {
			var msg = LW.error.format(response);
			LW.DHTML.popupError(msg);
		}
		return true;
	}
};

