text: 'use strict';
  
  var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
  
  var _ = require('underscore');
  var request = require('superagent');
  var debug = require('debug')('leancloud:request');
  var Promise = require('../promise');
  
  var requestsCount = 0;
  
  var ajax = function ajax(_ref) {
    var method = _ref.method,
        url = _ref.url,
        query = _ref.query,
        data = _ref.data,
        _ref$headers = _ref.headers,
        headers = _ref$headers === undefined ? {} : _ref$headers,
        onprogress = _ref.onprogress;
  
    var count = requestsCount++;
  
    debug('request(' + count + ')', method, url, query, data, headers);
  
    var flattenedQuery = {};
    if (query) {
      for (var k in query) {
        if (_typeof(query[k]) === 'object') {
          flattenedQuery[k] = JSON.stringify(query[k]);
        } else {
          flattenedQuery[k] = query[k];
        }
      }
    }
  
    return new Promise(function (resolve, reject) {
      var req = request(method, url).set(headers).query(flattenedQuery).send(data);
      if (onprogress) {
        req.on('progress', onprogress);
      }
      req.end(function (err, res) {
        if (res) {
          debug('response(' + count + ')', res.status, res.body || res.text, res.header);
        }
        if (err) {
          if (res) {
            err.statusCode = res.status;
            err.responseText = res.text;
            err.response = res.body;
          }
          return reject(err);
        }
        return resolve(res.body);
      });
    });
  };
  
  // Helper function to check null or undefined.
  var isNullOrUndefined = function isNullOrUndefined(x) {
    return _.isNull(x) || _.isUndefined(x);
  };
  
  var ensureArray = function ensureArray(target) {
    if (_.isArray(target)) {
      return target;
    }
    if (target === undefined || target === null) {
      return [];
    }
    return [target];
  };
  
  var transformFetchOptions = function transformFetchOptions() {
    var _ref2 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
        keys = _ref2.keys,
        include = _ref2.include,
        includeACL = _ref2.includeACL;
  
    var fetchOptions = {};
    if (keys) {
      fetchOptions.keys = ensureArray(keys).join(',');
    }
    if (include) {
      fetchOptions.include = ensureArray(include).join(',');
    }
    if (includeACL) {
      fetchOptions.returnACL = includeACL;
    }
    return fetchOptions;
  };
  
  var getSessionToken = function getSessionToken(authOptions) {
    if (authOptions.sessionToken) {
      return authOptions.sessionToken;
    }
    if (authOptions.user && typeof authOptions.user.getSessionToken === 'function') {
      return authOptions.user.getSessionToken();
    }
  };
  
  var tap = function tap(interceptor) {
    return function (value) {
      return interceptor(value), value;
    };
  };
  
  // Shared empty constructor function to aid in prototype-chain creation.
  var EmptyConstructor = function EmptyConstructor() {};
  
  // Helper function to correctly set up the prototype chain, for subclasses.
  // Similar to `goog.inherits`, but uses a hash of prototype properties and
  // class properties to be extended.
  var inherits = function inherits(parent, protoProps, staticProps) {
    var child;
  
    // The constructor function for the new subclass is either defined by you
    // (the "constructor" property in your `extend` definition), or defaulted
    // by us to simply call the parent's constructor.
    if (protoProps && protoProps.hasOwnProperty('constructor')) {
      child = protoProps.constructor;
    } else {
      /** @ignore */
      child = function child() {
        parent.apply(this, arguments);
      };
    }
  
    // Inherit class (static) properties from parent.
    _.extend(child, parent);
  
    // Set the prototype chain to inherit from `parent`, without calling
    // `parent`'s constructor function.
    EmptyConstructor.prototype = parent.prototype;
    child.prototype = new EmptyConstructor();
  
    // Add prototype properties (instance properties) to the subclass,
    // if supplied.
    if (protoProps) {
      _.extend(child.prototype, protoProps);
    }
  
    // Add static properties to the constructor function, if supplied.
    if (staticProps) {
      _.extend(child, staticProps);
    }
  
    // Correctly set child's `prototype.constructor`.
    child.prototype.constructor = child;
  
    // Set a convenience property in case the parent's prototype is
    // needed later.
    child.__super__ = parent.prototype;
  
    return child;
  };
  
  function parseDate(iso8601) {
    var regexp = new RegExp("^([0-9]{1,4})-([0-9]{1,2})-([0-9]{1,2})" + "T" + "([0-9]{1,2}):([0-9]{1,2}):([0-9]{1,2})" + "(.([0-9]+))?" + "Z$");
    var match = regexp.exec(iso8601);
    if (!match) {
      return null;
    }
  
    var year = match[1] || 0;
    var month = (match[2] || 1) - 1;
    var day = match[3] || 0;
    var hour = match[4] || 0;
    var minute = match[5] || 0;
    var second = match[6] || 0;
    var milli = match[8] || 0;
  
    return new Date(Date.UTC(year, month, day, hour, minute, second, milli));
  }
  
  module.exports = {
    ajax: ajax,
    isNullOrUndefined: isNullOrUndefined,
    ensureArray: ensureArray,
    transformFetchOptions: transformFetchOptions,
    getSessionToken: getSessionToken,
    tap: tap,
    inherits: inherits,
    parseDate: parseDate
  };