﻿/// <reference path="global.js" />
/*
Модуль для работы с HTTRequest-ом
*/
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);
        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];
//        for (var i = 0; i < this.Requests.length; i++)
//        {
//            if (this.Requests[i].Id == id)
//            {
//                result = this.Requests[i];
//                break;
//            }
//        }
        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;
