text: "use strict";
  var __extends = (this && this.__extends) || function (d, b) {
      for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
      function __() { this.constructor = d; }
      d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
  };
  var root_1 = require("../../util/root");
  var tryCatch_1 = require("../../util/tryCatch");
  var errorObject_1 = require("../../util/errorObject");
  var Observable_1 = require("../../Observable");
  var Subscriber_1 = require("../../Subscriber");
  var map_1 = require("../../operator/map");
  function getCORSRequest() {
      if (root_1.root.XMLHttpRequest) {
          var xhr = new root_1.root.XMLHttpRequest();
          if ('withCredentials' in xhr) {
              xhr.withCredentials = !!this.withCredentials;
          }
          return xhr;
      }
      else if (!!root_1.root.XDomainRequest) {
          return new root_1.root.XDomainRequest();
      }
      else {
          throw new Error('CORS is not supported by your browser');
      }
  }
  function getXMLHttpRequest() {
      if (root_1.root.XMLHttpRequest) {
          return new root_1.root.XMLHttpRequest();
      }
      else {
          var progId = void 0;
          try {
              var progIds = ['Msxml2.XMLHTTP', 'Microsoft.XMLHTTP', 'Msxml2.XMLHTTP.4.0'];
              for (var i = 0; i < 3; i++) {
                  try {
                      progId = progIds[i];
                      if (new root_1.root.ActiveXObject(progId)) {
                          break;
                      }
                  }
                  catch (e) {
                  }
              }
              return new root_1.root.ActiveXObject(progId);
          }
          catch (e) {
              throw new Error('XMLHttpRequest is not supported by your browser');
          }
      }
  }
  function ajaxGet(url, headers) {
      if (headers === void 0) { headers = null; }
      return new AjaxObservable({ method: 'GET', url: url, headers: headers });
  }
  exports.ajaxGet = ajaxGet;
  ;
  function ajaxPost(url, body, headers) {
      return new AjaxObservable({ method: 'POST', url: url, body: body, headers: headers });
  }
  exports.ajaxPost = ajaxPost;
  ;
  function ajaxDelete(url, headers) {
      return new AjaxObservable({ method: 'DELETE', url: url, headers: headers });
  }
  exports.ajaxDelete = ajaxDelete;
  ;
  function ajaxPut(url, body, headers) {
      return new AjaxObservable({ method: 'PUT', url: url, body: body, headers: headers });
  }
  exports.ajaxPut = ajaxPut;
  ;
  function ajaxGetJSON(url, headers) {
      return new AjaxObservable({ method: 'GET', url: url, responseType: 'json', headers: headers })
          .lift(new map_1.MapOperator(function (x, index) { return x.response; }, null));
  }
  exports.ajaxGetJSON = ajaxGetJSON;
  ;
  /**
   * We need this JSDoc comment for affecting ESDoc.
   * @extends {Ignored}
   * @hide true
   */
  var AjaxObservable = (function (_super) {
      __extends(AjaxObservable, _super);
      function AjaxObservable(urlOrRequest) {
          var _this = _super.call(this) || this;
          var request = {
              async: true,
              createXHR: function () {
                  return this.crossDomain ? getCORSRequest.call(this) : getXMLHttpRequest();
              },
              crossDomain: false,
              withCredentials: false,
              headers: {},
              method: 'GET',
              responseType: 'json',
              timeout: 0
          };
          if (typeof urlOrRequest === 'string') {
              request.url = urlOrRequest;
          }
          else {
              for (var prop in urlOrRequest) {
                  if (urlOrRequest.hasOwnProperty(prop)) {
                      request[prop] = urlOrRequest[prop];
                  }
              }
          }
          _this.request = request;
          return _this;
      }
      AjaxObservable.prototype._subscribe = function (subscriber) {
          return new AjaxSubscriber(subscriber, this.request);
      };
      return AjaxObservable;
  }(Observable_1.Observable));
  /**
   * Creates an observable for an Ajax request with either a request object with
   * url, headers, etc or a string for a URL.
   *
   * @example
   * source = Rx.Observable.ajax('/products');
   * source = Rx.Observable.ajax({ url: 'products', method: 'GET' });
   *
   * @param {string|Object} request Can be one of the following:
   *   A string of the URL to make the Ajax call.
   *   An object with the following properties
   *   - url: URL of the request
   *   - body: The body of the request
   *   - method: Method of the request, such as GET, POST, PUT, PATCH, DELETE
   *   - async: Whether the request is async
   *   - headers: Optional headers
   *   - crossDomain: true if a cross domain request, else false
   *   - createXHR: a function to override if you need to use an alternate
   *   XMLHttpRequest implementation.
   *   - resultSelector: a function to use to alter the output value type of
   *   the Observable. Gets {@link AjaxResponse} as an argument.
   * @return {Observable} An observable sequence containing the XMLHttpRequest.
   * @static true
   * @name ajax
   * @owner Observable
  */
  AjaxObservable.create = (function () {
      var create = function (urlOrRequest) {
          return new AjaxObservable(urlOrRequest);
      };
      create.get = ajaxGet;
      create.post = ajaxPost;
      create.delete = ajaxDelete;
      create.put = ajaxPut;
      create.getJSON = ajaxGetJSON;
      return create;
  })();
  exports.AjaxObservable = AjaxObservable;
  /**
   * We need this JSDoc comment for affecting ESDoc.
   * @ignore
   * @extends {Ignored}
   */
  var AjaxSubscriber = (function (_super) {
      __extends(AjaxSubscriber, _super);
      function AjaxSubscriber(destination, request) {
          var _this = _super.call(this, destination) || this;
          _this.request = request;
          _this.done = false;
          var headers = request.headers = request.headers || {};
          // force CORS if requested
          if (!request.crossDomain && !headers['X-Requested-With']) {
              headers['X-Requested-With'] = 'XMLHttpRequest';
          }
          // ensure content type is set
          if (!('Content-Type' in headers) && !(root_1.root.FormData && request.body instanceof root_1.root.FormData) && typeof request.body !== 'undefined') {
              headers['Content-Type'] = 'application/x-www-form-urlencoded; charset=UTF-8';
          }
          // properly serialize body
          request.body = _this.serializeBody(request.body, request.headers['Content-Type']);
          _this.send();
          return _this;
      }
      AjaxSubscriber.prototype.next = function (e) {
          this.done = true;
          var _a = this, xhr = _a.xhr, request = _a.request, destination = _a.destination;
          var response = new AjaxResponse(e, xhr, request);
          destination.next(response);
      };
      AjaxSubscriber.prototype.send = function () {
          var _a = this, request = _a.request, _b = _a.request, user = _b.user, method = _b.method, url = _b.url, async = _b.async, password = _b.password, headers = _b.headers, body = _b.body;
          var createXHR = request.createXHR;
          var xhr = tryCatch_1.tryCatch(createXHR).call(request);
          if (xhr === errorObject_1.errorObject) {
              this.error(errorObject_1.errorObject.e);
          }
          else {
              this.xhr = xhr;
              // set up the events before open XHR
              // https://developer.mozilla.org/en/docs/Web/API/XMLHttpRequest/Using_XMLHttpRequest
              // You need to add the event listeners before calling open() on the request.
              // Otherwise the progress events will not fire.
              this.setupEvents(xhr, request);
              // open XHR
              var result = void 0;
              if (user) {
                  result = tryCatch_1.tryCatch(xhr.open).call(xhr, method, url, async, user, password);
              }
              else {
                  result = tryCatch_1.tryCatch(xhr.open).call(xhr, method, url, async);
              }
              if (result === errorObject_1.errorObject) {
                  this.error(errorObject_1.errorObject.e);
                  return null;
              }
              // timeout and responseType can be set once the XHR is open
              xhr.timeout = request.timeout;
              xhr.responseType = request.responseType;
              // set headers
              this.setHeaders(xhr, headers);
              // finally send the request
              result = body ? tryCatch_1.tryCatch(xhr.send).call(xhr, body) : tryCatch_1.tryCatch(xhr.send).call(xhr);
              if (result === errorObject_1.errorObject) {
                  this.error(errorObject_1.errorObject.e);
                  return null;
              }
          }
          return xhr;
      };
      AjaxSubscriber.prototype.serializeBody = function (body, contentType) {
          if (!body || typeof body === 'string') {
              return body;
          }
          else if (root_1.root.FormData && body instanceof root_1.root.FormData) {
              return body;
          }
          if (contentType) {
              var splitIndex = contentType.indexOf(';');
              if (splitIndex !== -1) {
                  contentType = contentType.substring(0, splitIndex);
              }
          }
          switch (contentType) {
              case 'application/x-www-form-urlencoded':
                  return Object.keys(body).map(function (key) { return encodeURI(key) + "=" + encodeURI(body[key]); }).join('&');
              case 'application/json':
                  return JSON.stringify(body);
              default:
                  return body;
          }
      };
      AjaxSubscriber.prototype.setHeaders = function (xhr, headers) {
          for (var key in headers) {
              if (headers.hasOwnProperty(key)) {
                  xhr.setRequestHeader(key, headers[key]);
              }
          }
      };
      AjaxSubscriber.prototype.setupEvents = function (xhr, request) {
          var progressSubscriber = request.progressSubscriber;
          function xhrTimeout(e) {
              var _a = xhrTimeout, subscriber = _a.subscriber, progressSubscriber = _a.progressSubscriber, request = _a.request;
              if (progressSubscriber) {
                  progressSubscriber.error(e);
              }
              subscriber.error(new AjaxTimeoutError(this, request)); //TODO: Make betterer.
          }
          ;
          xhr.ontimeout = xhrTimeout;
          xhrTimeout.request = request;
          xhrTimeout.subscriber = this;
          xhrTimeout.progressSubscriber = progressSubscriber;
          if (xhr.upload && 'withCredentials' in xhr) {
              if (progressSubscriber) {
                  var xhrProgress_1;
                  xhrProgress_1 = function (e) {
                      var progressSubscriber = xhrProgress_1.progressSubscriber;
                      progressSubscriber.next(e);
                  };
                  if (root_1.root.XDomainRequest) {
                      xhr.onprogress = xhrProgress_1;
                  }
                  else {
                      xhr.upload.onprogress = xhrProgress_1;
                  }
                  xhrProgress_1.progressSubscriber = progressSubscriber;
              }
              var xhrError_1;
              xhrError_1 = function (e) {
                  var _a = xhrError_1, progressSubscriber = _a.progressSubscriber, subscriber = _a.subscriber, request = _a.request;
                  if (progressSubscriber) {
                      progressSubscriber.error(e);
                  }
                  subscriber.error(new AjaxError('ajax error', this, request));
              };
              xhr.onerror = xhrError_1;
              xhrError_1.request = request;
              xhrError_1.subscriber = this;
              xhrError_1.progressSubscriber = progressSubscriber;
          }
          function xhrReadyStateChange(e) {
              var _a = xhrReadyStateChange, subscriber = _a.subscriber, progressSubscriber = _a.progressSubscriber, request = _a.request;
              if (this.readyState === 4) {
                  // normalize IE9 bug (http://bugs.jquery.com/ticket/1450)
                  var status_1 = this.status === 1223 ? 204 : this.status;
                  var response = (this.responseType === 'text' ? (this.response || this.responseText) : this.response);
                  // fix status code when it is 0 (0 status is undocumented).
                  // Occurs when accessing file resources or on Android 4.1 stock browser
                  // while retrieving files from application cache.
                  if (status_1 === 0) {
                      status_1 = response ? 200 : 0;
                  }
                  if (200 <= status_1 && status_1 < 300) {
                      if (progressSubscriber) {
                          progressSubscriber.complete();
                      }
                      subscriber.next(e);
                      subscriber.complete();
                  }
                  else {
                      if (progressSubscriber) {
                          progressSubscriber.error(e);
                      }
                      subscriber.error(new AjaxError('ajax error ' + status_1, this, request));
                  }
              }
          }
          ;
          xhr.onreadystatechange = xhrReadyStateChange;
          xhrReadyStateChange.subscriber = this;
          xhrReadyStateChange.progressSubscriber = progressSubscriber;
          xhrReadyStateChange.request = request;
      };
      AjaxSubscriber.prototype.unsubscribe = function () {
          var _a = this, done = _a.done, xhr = _a.xhr;
          if (!done && xhr && xhr.readyState !== 4 && typeof xhr.abort === 'function') {
              xhr.abort();
          }
          _super.prototype.unsubscribe.call(this);
      };
      return AjaxSubscriber;
  }(Subscriber_1.Subscriber));
  exports.AjaxSubscriber = AjaxSubscriber;
  /**
   * A normalized AJAX response.
   *
   * @see {@link ajax}
   *
   * @class AjaxResponse
   */
  var AjaxResponse = (function () {
      function AjaxResponse(originalEvent, xhr, request) {
          this.originalEvent = originalEvent;
          this.xhr = xhr;
          this.request = request;
          this.status = xhr.status;
          this.responseType = xhr.responseType || request.responseType;
          switch (this.responseType) {
              case 'json':
                  if ('response' in xhr) {
                      //IE does not support json as responseType, parse it internally
                      this.response = xhr.responseType ? xhr.response : JSON.parse(xhr.response || xhr.responseText || 'null');
                  }
                  else {
                      this.response = JSON.parse(xhr.responseText || 'null');
                  }
                  break;
              case 'xml':
                  this.response = xhr.responseXML;
                  break;
              case 'text':
              default:
                  this.response = ('response' in xhr) ? xhr.response : xhr.responseText;
                  break;
          }
      }
      return AjaxResponse;
  }());
  exports.AjaxResponse = AjaxResponse;
  /**
   * A normalized AJAX error.
   *
   * @see {@link ajax}
   *
   * @class AjaxError
   */
  var AjaxError = (function (_super) {
      __extends(AjaxError, _super);
      function AjaxError(message, xhr, request) {
          var _this = _super.call(this, message) || this;
          _this.message = message;
          _this.xhr = xhr;
          _this.request = request;
          _this.status = xhr.status;
          return _this;
      }
      return AjaxError;
  }(Error));
  exports.AjaxError = AjaxError;
  /**
   * @see {@link ajax}
   *
   * @class AjaxTimeoutError
   */
  var AjaxTimeoutError = (function (_super) {
      __extends(AjaxTimeoutError, _super);
      function AjaxTimeoutError(xhr, request) {
          return _super.call(this, 'ajax timeout', xhr, request) || this;
      }
      return AjaxTimeoutError;
  }(AjaxError));
  exports.AjaxTimeoutError = AjaxTimeoutError;
  //# sourceMappingURL=AjaxObservable.js.map