/// <reference path="ITransport.ts" />
/// <reference path="../../env/UserAgent.ts" />
/// <reference path="../Request.ts" />
/// <reference path="../Response.ts" />
var econda;
(function (econda) {
    var ajax;
    (function (ajax) {
        var transport;
        (function (transport) {
            var Response = econda.ajax.Response;
            /**
             * XHR Post transport implementation. There's no reason to use this class directly. See {@link econda.ajax.Request}.
             * @class econda.ajax.transport.Post
             */
            var Post = (function () {
                function Post() {
                    this._initialized = false;
                    this._allHeaders = {};
                }
                Post.prototype.setRequest = function (request) {
                    this._request = request;
                };
                Post.prototype.getRequest = function () {
                    return this._request;
                };
                Post.prototype.hasHeaders = function () {
                    if (Object.keys) {
                        return (Object.keys(this._allHeaders).length > 0);
                    }
                    else {
                        var keys = [], k;
                        for (k in this._allHeaders) {
                            if (Object.prototype.hasOwnProperty.call(this._allHeaders, k)) {
                                keys.push(k);
                            }
                        }
                        return keys.length > 0;
                    }
                };
                /**
                 * Send request
                 * @param {econda.ajax.Request} request
                 */
                Post.prototype.init = function () {
                    this.initWriterInstance();
                    this.initXmlHttpRequestInstance();
                    this.appendCallbacks();
                    this._xhr.open("POST", this.getRequestUriWithParams(), true);
                    this._xhr.timeout = this._request.getTimeoutMilliseconds();
                    if (this._request.isXDomainRequest() && this._request.getWithCredentials() && this._xhr instanceof XMLHttpRequest) {
                        this._xhr.withCredentials = true;
                    }
                    this.appendHeaders();
                    this._initialized = true;
                };
                Post.prototype.send = function () {
                    var cmp = this;
                    if (!this._initialized) {
                        this.init();
                    }
                    setTimeout(function () {
                        cmp._xhr.send(cmp.getEncodedRequestData());
                        var callback = cmp._request.getAfterSend();
                        if (callback) {
                            callback();
                        }
                    }, 20);
                };
                /**
                 * Setup writer instance
                 * @returns {String}
                 */
                Post.prototype.initWriterInstance = function () {
                    var data = this._request.getData();
                    var writer = this._request.getWriter();
                    // auto detect writer?
                    if (writer == null && data) {
                        if (typeof data == 'object') {
                            writer = new econda.ajax.writer.FormEncodedWriter();
                        }
                    }
                    if (writer) {
                        writer.setData(this._request.getData());
                        this._writer = writer;
                    }
                };
                /**
                 * Add headers from request and writer to XMLHttpRequest object.
                 * @private
                 */
                Post.prototype.appendHeaders = function () {
                    var headers = {
                        "Content-Type": "text/plain"
                    };
                    if (this._request.isXDomainRequest() == false) {
                        // only for local requests, it would cause x-domain requests to be "not so simple requests"
                        // and so this would cause a prefly options request
                        headers["X-Requested-With"] = "XMLHttpRequest";
                    }
                    // add headers from writer, e.g. content type
                    if (this._writer) {
                        var headersFromWriter = this._writer.getHeaders();
                        if (headersFromWriter) {
                            for (var name in headersFromWriter) {
                                headers[name] = headersFromWriter[name];
                            }
                        }
                    }
                    // add headers from request object
                    var headersFromRequest = this._request.getHeaders();
                    if (headersFromRequest) {
                        for (var name in headersFromRequest) {
                            headers[name] = headersFromRequest[name];
                        }
                    }
                    this._allHeaders = headers;
                    // append to xhr object (not possible on XDomainRequest objects, <= IE10)
                    if (typeof this._xhr.setRequestHeader != 'undefined') {
                        for (var name in headers) {
                            this._xhr.setRequestHeader(name, headers[name]);
                        }
                    }
                    return this;
                };
                /**
                 * Get data from request using configured writer. This is not the right place for auto detection of content type (s. initWriter).
                 * @private
                 */
                Post.prototype.getEncodedRequestData = function () {
                    var ret = "";
                    if (this._writer) {
                        ret = this._writer.getBody();
                    }
                    else {
                        ret = "" + this._request.getData();
                    }
                    return ret;
                };
                /**
                 * Checks if given request can be send with current browser
                 * @returns {Boolean}
                 */
                Post.prototype.isSupportedRequest = function () {
                    this.initXmlHttpRequestInstance();
                    var isXDomainRequest = this._request.isXDomainRequest();
                    var ok = true;
                    // ie <= v 8 does not support xdomain request
                    ok = ok && (isXDomainRequest == false || this._isOldIE() == false);
                    // xdomain has header restrictions - FIXME, some headers are allowed, others not - we have to check this here
                    ok = ok && (this.hasHeaders() == false)
                        || ((typeof this._xhr['setRequestHeader'] != 'undefined') && (this._isOldIE() == false));
                    // withCredentials is not supported on XDomainRequest (IE 8)
                    ok = ok && (this._request.getWithCredentials() == false || this._xhr instanceof XMLHttpRequest);
                    return ok;
                };
                /**
                 * This old ie versions do have a setRequestHeader method, but they will show a confirm dialog to users if we
                 * use the XDomainRequest object to perform x domain requests
                 * @private
                 */
                Post.prototype._isOldIE = function () {
                    var ua = econda.env.UserAgent;
                    if (ua.getName() != ua.INTERNET_EXPLORER) {
                        return false;
                    }
                    if (ua.getVersion() >= 8) {
                        return false;
                    }
                    return true;
                };
                /**
                 * Create and return instance of XmlHttpRequest object for all browsers.
                 * @private
                 * @returns {XMLHttpRequest}
                 */
                Post.prototype.initXmlHttpRequestInstance = function () {
                    var isXDomainRequest = this._request.isXDomainRequest();
                    // init xhr only if not already done. We need this for unit tests
                    if (!this._xhr) {
                        if (isXDomainRequest && typeof window["XDomainRequest"] != 'undefined') {
                            this._xhr = new window["XDomainRequest"]();
                        }
                        else if (typeof XMLHttpRequest != 'undefined') {
                            this._xhr = new XMLHttpRequest();
                        }
                        else {
                            this._xhr = new ActiveXObject('Microsoft.XMLHTTP');
                        }
                    }
                };
                /**
                 * Get uri from request object with parameters appended
                 * @param {String} url
                 * @param {Object} params
                 * @returns {String} request uri incl. parameters
                 * @private
                 */
                Post.prototype.getRequestUriWithParams = function () {
                    var uri = this._request.getUri();
                    var params = this._request.getParams();
                    return uri.clone().appendParams(params).toString();
                };
                /**
                 * @private
                 */
                Post.prototype.appendCallbacks = function () {
                    var cmp = this;
                    this._xhr.onreadystatechange = function () {
                        cmp.onReadyStateChange.apply(cmp, arguments);
                    };
                    return this;
                };
                /**
                 * Callback for xhr onreadystatechange. Must inform the request when it's done.
                 * @private
                 */
                Post.prototype.onReadyStateChange = function () {
                    var xhr = this._xhr; // XmlHttpRequest
                    var request = this._request; // econda.ajax.IRequest
                    if (xhr.readyState == 4) {
                        var result = new Response();
                        result.responseText = xhr.responseText;
                        result.status = xhr.status;
                        result.isError = (xhr.status != 200);
                        request.handleResponse(result);
                    }
                };
                return Post;
            }());
            transport.Post = Post; // end of class
        })(transport = ajax.transport || (ajax.transport = {}));
    })(ajax = econda.ajax || (econda.ajax = {}));
})(econda || (econda = {})); // end of module