var net;
if (!net || !net.canuda) {
    throw new Error('net.canuda has not been loaded!');
}

net.canuda.Ajax = function() {
//private:
    var TIMEOUT = 30000;

    var getParams = function(params) {
        if (typeof params == 'string') { return params; }
        var str = '';
        for (var key in params) {
            str += key + '=' + params[key] + '&';
        }
        return str.slice(0, -1);
    };

    var getXHR = function() {
        if (window.XMLHttpRequest) {
            return (getXHR = function() {
                return new window.XMLHttpRequest();
            })();
        } else if (window.ActiveXObject) {
            return (getXHR = function() {
                return new window.ActiveXObject('Microsoft.XMLHTTP');
            })();
        } else {
            throw new Error('XMLHttpRequest not supported');
        }
    };

//public:
    return {
        Method: {
            get: 'GET',
            post: 'POST'
        },

        call: function(params) {
            var aborted = false;
            var req = getXHR();
            var timeout = params.timeout || TIMEOUT;
            var url = params.url || '';
            var timer = setTimeout(function() {
                aborted = true;
                req.abort();
                if (params.onTimeout) { params.onTimeout(); }
                else if (params.onError) { params.onError(); }
            }, timeout);
            req.onreadystatechange = function() {
                if (aborted) { return; }
                if (req.readyState != 4) { return; }
                clearTimeout(timer);
                if (req.status != 200) {
                    if (params.onError) { params.onError(req); }
                    return;
                }
                if (params.onComplete) { params.onComplete(req); }
            };
            switch (params.method) {
                case undefined:
                case this.Method.get:
                    url += '?' + getParams(params.params);
                    req.open(this.Method.get, url);
                    req.send(null);
                    break;
                case this.Method.post:
                    req.open(this.Method.post, url);
                    req.setRequestHeader('Content-type',
                                         'application/x-www-form-urlencoded');
                    req.send(getParams(params.params));
                    break;
                default:
                    throw new Error('Method not supported');
            }
        }
    };
}();
