/**
 * @file xhr.js
 */

/**
 * A wrapper for videojs.xhr that tracks bandwidth.
 *
 * @param {Object} options options for the XHR
 * @param {Function} callback the callback to call when done
 * @return {Request} the xhr request that is going to be made
 */
'use strict';

Object.defineProperty(exports, '__esModule', {
  value: true
});

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }

var _videoJs = require('video.js');

var _videoJs2 = _interopRequireDefault(_videoJs);

var xhrFactory = function xhrFactory() {
  var xhr = function XhrFunction(options, callback) {
    // Add a default timeout for all hls requests
    options = (0, _videoJs.mergeOptions)({
      timeout: 45e3
    }, options);

    // Allow an optional user-specified function to modify the option
    // object before we construct the xhr request
    var beforeRequest = XhrFunction.beforeRequest || _videoJs2['default'].Hls.xhr.beforeRequest;

    if (beforeRequest && typeof beforeRequest === 'function') {
      var newOptions = beforeRequest(options);

      if (newOptions) {
        options = newOptions;
      }
    }

    var request = (0, _videoJs.xhr)(options, function (error, response) {
      var reqResponse = request.response;

      if (!error && reqResponse) {
        request.responseTime = Date.now();
        request.roundTripTime = request.responseTime - request.requestTime;
        request.bytesReceived = reqResponse.byteLength || reqResponse.length;
        if (!request.bandwidth) {
          request.bandwidth = Math.floor(request.bytesReceived / request.roundTripTime * 8 * 1000);
        }
      }

      // videojs.xhr now uses a specific code on the error
      // object to signal that a request has timed out instead
      // of setting a boolean on the request object
      if (error && error.code === 'ETIMEDOUT') {
        request.timedout = true;
      }

      // videojs.xhr no longer considers status codes outside of 200 and 0
      // (for file uris) to be errors, but the old XHR did, so emulate that
      // behavior. Status 206 may be used in response to byterange requests.
      if (!error && !request.aborted && response.statusCode !== 200 && response.statusCode !== 206 && response.statusCode !== 0) {
        error = new Error('XHR Failed with a response of: ' + (request && (reqResponse || request.responseText)));
      }

      callback(error, request);
    });
    var originalAbort = request.abort;

    request.abort = function () {
      request.aborted = true;
      return originalAbort.apply(request, arguments);
    };
    request.uri = options.uri;
    request.requestTime = Date.now();
    return request;
  };

  return xhr;
};

exports['default'] = xhrFactory;
module.exports = exports['default'];