﻿function Request(id) {
    this.Id = null;
    if (id) {
        this.Id = id;
        $server.Requests[id] = this;
    }
    this.Request = $server.CreateRequest();
    this.Stop = function () {
        this.Request.onreadystatechange = function () { };
        $server.OnAbort(this);
        this.Request.abort();
    }
    this.Send = function (url, onSuccess, onError, postData, text, async) {
        var req = this.Request;
        if (!req) return;
        this.Stop();
        var method = (postData) ? "POST" : "GET";
        req.open(method, url, async);
        if (req.overrideMimeType)
            req.overrideMimeType("text/plain");
        req.setRequestHeader('User-Agent', 'XMLHTTP/1.0');
        if (postData)
            req.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
        if (postData == null)
            postData = "";
        if (!$G.IsString(postData))
            postData = $server.GetPostString(postData);
        var _toCall = function () {
            if (this.Request.readyState != 4) { return; }
            else {
                try {
                    if (this.Request.status != 200 && this.Request.status != 304) {
                        if (onError)
                            onError(this.Request);
                        $Server.OnError(this.Request);
                        $server.Requests[this.id] = null;
                        return;
                    }
                }
                catch (e) {
                    if (onError)
                        onError(this.Request);
                    $Server.OnError(this.Request);
                    $server.Requests[this.id] = null;
                    return;
                }
                if (onSuccess)
                    onSuccess(this.Request);
                $Server.OnSuccess(this.Request);
                $server.Requests[this.id] = null;
            }
        } .bind(this);
        if (req.onload)
            req.onload = _toCall;
        else
            req.onreadystatechange = _toCall;
        if (req.readyState == 4) return;
        $Server.OnStart(req);
        req.send(postData);
        try {
            if ($G.Browser.Detect.gecko)
                if (!async && req.onreadystatechange == null)
                    _toCall();
        } catch (e) {
            _toCall();
        }
    }
}
var $server =
{
    // добавляет handler в реакцию на генерацию события 
    // семейства AddOn*
    AddOnStart: function (handler) {
        this._onStartSubscribers.push(handler);
        return this._onStartSubscribers.length;
    },
    AddOnAbort: function (handler) {
        this._onAbortSubscribers.push(handler);
        return this._onAbortSubscribers.length;
    },
    AddOnSuccess: function (handler) {
        this._onSuccessSubscribers.push(handler);
        return this._onStartSubscribers.length;
    },
    AddOnError: function (handler) {
        this._onErrorSubscribers.push(handler);
        return this._onStartSubscribers.length;
    },
    // obj это либо хэндлер функции которая 
    // добавлялась через AddOn* либо идентификатор хэндлера
    // возвращаемый фунциями семейства AddOn*
    RemoveOnStart: function (obj) {
        if (typeof (obj) == 'number')
            this._onStartSubscribers.splice(obj, 1);
        else
            this._onStartSubscribers.remove(obj);
    },
    RemoveOnAbort: function (obj) {
        if (typeof (obj) == 'number')
            this._onAbortSubscribers.splice(obj, 1);
        else
            this._onAbortSubscribers.remove(obj);
    },
    RemoveOnSuccess: function (obj) {
        if (typeof (obj) == 'number')
            this._onSuccessSubscribers.splice(obj, 1);
        else
            this._onSuccessSubscribers.remove(obj);
    },
    RemoveOnError: function (obj) {
        if (typeof (obj) == 'number')
            this._onErrorSubscribers.splice(obj, 1);
        else
            this._onErrorSubscribers.remove(obj);
    },
    OnStart: function (request) {
        for (var i = 0; i < this._onStartSubscribers.length; i++)
            this._onStartSubscribers[i](request);
    },
    OnSuccess: function (request) {
        for (var i = 0; i < this._onSuccessSubscribers.length; i++)
            this._onSuccessSubscribers[i](request);
    },
    OnError: function (request) {
        for (var i = 0; i < this._onErrorSubscribers.length; i++)
            this._onErrorSubscribers[i](request);
    },
    OnAbort: function (request) {
        for (var i = 0; i < this._onAbortSubscribers.length; i++)
            this._onAbortSubscribers[i](request);
    },
    _onStartSubscribers: new Array(),
    _onSuccessSubscribers: new Array(),
    _onErrorSubscribers: new Array(),
    _onAbortSubscribers: new Array(),
    Requests: {},
    InStack: function (id) {
        var res = false;
        for (var i = 0; i < this.Requests.length; i++) {
            if ((this.Requests[i].Id == id) && (this.Requests[i].Id != null)) {
                res = true;
                break;
            }
        }
        return res;
    },
    GetRequest: function (id) {
        var result = this.Requests[id];
        if (result == null)
            result = new Request(id);
        return result;
    },
    HttpFactories: [
        function () { return new XMLHttpRequest() },
	    function () { return new ActiveXObject("Msxml2.XMLHTTP") },
	    function () { return new ActiveXObject("Msxml3.XMLHTTP") },
	    function () { return new ActiveXObject("Microsoft.XMLHTTP") }
    ],
    CreateRequest: function () {
        var xmlhttp = false;
        for (var i = 0; i < $server.HttpFactories.length; i++) {
            try {
                xmlhttp = $server.HttpFactories[i]();
            }
            catch (e) {
                continue;
            }
            break;
        }
        return xmlhttp;
    },
    Send: function (url, success, error, postData, async, id) {
        var req = $server.GetRequest(id); //new Request(id);
        req.Send(url, success, error, postData, null, async);
        return req;
    },
    GetPostString: function (obj) {
        var result = new String();
        result = "";
        for (var prop in obj) {
            result += prop + "=" + (obj[prop] == null ? "" : obj[prop]).toString().replace(/\+/gi, "%2B").replace(/\&/gi, "%26").replace(/\=/gi, "%3D") + "&";
        }
        result = result.substring(0, result.length - 1);
        return result;
    }
}
var $Server = $server;
