'use strict';

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

var _regeneratorRuntime = require('@babel/runtime/regenerator');
var _asyncToGenerator = require('@babel/runtime/helpers/asyncToGenerator');
var _classCallCheck = require('@babel/runtime/helpers/classCallCheck');
var _createClass = require('@babel/runtime/helpers/createClass');
var _assertThisInitialized = require('@babel/runtime/helpers/assertThisInitialized');
var _get = require('@babel/runtime/helpers/get');
var _inherits = require('@babel/runtime/helpers/inherits');
var _possibleConstructorReturn = require('@babel/runtime/helpers/possibleConstructorReturn');
var _getPrototypeOf = require('@babel/runtime/helpers/getPrototypeOf');
var _defineProperty = require('@babel/runtime/helpers/defineProperty');
var http = require('http');
var utils = require('@teclone/utils');
var FileServer = require('./FileServer');
var Utils = require('./Utils');

function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }

var _regeneratorRuntime__default = /*#__PURE__*/_interopDefaultLegacy(_regeneratorRuntime);
var _asyncToGenerator__default = /*#__PURE__*/_interopDefaultLegacy(_asyncToGenerator);
var _classCallCheck__default = /*#__PURE__*/_interopDefaultLegacy(_classCallCheck);
var _createClass__default = /*#__PURE__*/_interopDefaultLegacy(_createClass);
var _assertThisInitialized__default = /*#__PURE__*/_interopDefaultLegacy(_assertThisInitialized);
var _get__default = /*#__PURE__*/_interopDefaultLegacy(_get);
var _inherits__default = /*#__PURE__*/_interopDefaultLegacy(_inherits);
var _possibleConstructorReturn__default = /*#__PURE__*/_interopDefaultLegacy(_possibleConstructorReturn);
var _getPrototypeOf__default = /*#__PURE__*/_interopDefaultLegacy(_getPrototypeOf);
var _defineProperty__default = /*#__PURE__*/_interopDefaultLegacy(_defineProperty);

function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; }

function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty__default['default'](target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }

function _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = _getPrototypeOf__default['default'](Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf__default['default'](this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn__default['default'](this, result); }; }

function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } }
var Response = /*#__PURE__*/function (_ServerResponse) {
  _inherits__default['default'](Response, _ServerResponse);

  var _super = _createSuper(Response);

  function Response(req) {
    var _this;

    _classCallCheck__default['default'](this, Response);

    _this = _super.call(this, req);

    _defineProperty__default['default'](_assertThisInitialized__default['default'](_this), "config", {});

    _defineProperty__default['default'](_assertThisInitialized__default['default'](_this), "request", {});

    _defineProperty__default['default'](_assertThisInitialized__default['default'](_this), "logger", {});

    _defineProperty__default['default'](_assertThisInitialized__default['default'](_this), "errorCallback", null);

    _defineProperty__default['default'](_assertThisInitialized__default['default'](_this), "startedAt", {});

    _defineProperty__default['default'](_assertThisInitialized__default['default'](_this), "endedAt", {});

    _this.request = req;
    return _this;
  }

  _createClass__default['default'](Response, [{
    key: "end",
    value:
    /**
     * ends the response with optional response data, and optional data encoding
     * @param data optional data to send. either string or buffer
     * @param encoding data encoding if not buffer
     */
    function end(data, encoding) {
      var _this2 = this;

      var resolvedData = data;

      if (!Buffer.isBuffer(data) && !utils.isString(data)) {
        if (utils.isObject(data)) {
          resolvedData = JSON.stringify(data);
        } else {
          resolvedData = '';
        }
      }

      return new Promise(function (resolve) {
        if (encoding) {
          _get__default['default'](_getPrototypeOf__default['default'](Response.prototype), "end", _this2).call(_this2, resolvedData, encoding, function () {
            resolve(true);
          });
        } else {
          _get__default['default'](_getPrototypeOf__default['default'](Response.prototype), "end", _this2).call(_this2, resolvedData, function () {
            resolve(true);
          });
        }
      });
    }
    /**
     * sets response header
     * @param name response header name
     * @param value response header value
     */

  }, {
    key: "setHeader",
    value: function setHeader(name, value) {
      _get__default['default'](_getPrototypeOf__default['default'](Response.prototype), "setHeader", this).call(this, name, value);

      return this;
    }
    /**
     * sets multiple response headers
     * @param headers object containing response header name value pairs
     */

  }, {
    key: "setHeaders",
    value: function setHeaders(headers) {
      var _this3 = this;

      Object.keys(headers).forEach(function (key) {
        _this3.setHeader(key, headers[key]);
      });
      return this;
    }
    /**
     * removes a single set response header at a time. function is chainable
     * @param name response header to remove
     */

  }, {
    key: "removeHeader",
    value: function removeHeader(name) {
      _get__default['default'](_getPrototypeOf__default['default'](Response.prototype), "removeHeader", this).call(this, name);

      return this;
    }
    /**
     * remove response headers that are already set. function is chainable
     * @param names - comma separated list of header names to remove
     */

  }, {
    key: "removeHeaders",
    value: function removeHeaders() {
      var _this4 = this;

      for (var _len = arguments.length, names = new Array(_len), _key = 0; _key < _len; _key++) {
        names[_key] = arguments[_key];
      }

      names.forEach(function (name) {
        _this4.removeHeader(name);
      });
      return this;
    }
    /**
     * sets response status code
     * @param code - the response code
     */

  }, {
    key: "status",
    value: function status(code) {
      this.statusCode = code;
      return this;
    }
    /**
     * sends json response back to the client.
     * @param data - the json string or json object which will be stringified
     */

  }, {
    key: "json",
    value: function json(data) {
      if (!utils.isString(data)) {
        data = JSON.stringify(data);
      }

      return this.setHeader('Content-Type', 'application/json').end(data);
    }
    /**
     * Redirect client to the given url
     */

  }, {
    key: "redirect",
    value: function redirect(path) {
      var status = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 302;
      return this.status(status).setHeader('Location', path).end();
    }
    /**
     * sends a file download attachment to the client
     * @param filePath - relative or absolute file path
     * @param filename - suggested file download name
     */

  }, {
    key: "download",
    value: function download(filePath, filename) {
      var fileServer = new FileServer.FileServer(this.config, this.request, this);
      return fileServer.serveDownload(filePath, filename);
    }
    /**
     *
     */

  }, {
    key: "processJson",
    value: function processJson(response, options) {
      var _ref = response || {},
          _ref$statusCode = _ref.statusCode,
          statusCode = _ref$statusCode === void 0 ? 200 : _ref$statusCode,
          message = _ref.message,
          _ref$data = _ref.data,
          data = _ref$data === void 0 ? {} : _ref$data,
          _ref$headers = _ref.headers,
          headers = _ref$headers === void 0 ? {} : _ref$headers,
          _ref$ttl = _ref.ttl,
          ttl = _ref$ttl === void 0 ? 0 : _ref$ttl;

      var _ref2 = options || {},
          onSuccess = _ref2.onSuccess,
          onError = _ref2.onError;

      if (statusCode < 300) {
        return this.status(statusCode).setHeaders(headers).json({
          status: 'success',
          statusCode: statusCode,
          message: message || 'Request successful',
          data: data,
          ttl: ttl
        }).then(function (result) {
          return (onSuccess === null || onSuccess === void 0 ? void 0 : onSuccess(response)) || result;
        });
      }

      return this.status(statusCode).setHeaders(headers).json({
        status: 'error',
        statusCode: statusCode,
        message: message || 'Request failed',
        data: data,
        ttl: ttl
      }).then(function (result) {
        return (onError === null || onError === void 0 ? void 0 : onError(response)) || result;
      });
    }
    /**
     * sends json error data back to the client
     * @param statusCode http error status code, defaults to 400
     * @param message short message to return to client
     * @param errorData error data object, defaults to empty object
     */

  }, {
    key: "jsonError",
    value: function jsonError(response) {
      return this.processJson(_objectSpread({
        statusCode: 400
      }, response));
    }
    /**
     * sends json success data back to the client
     * @param statusCode http status code, defaults to 200
     * @param message short message to return to client
     * @param successData success data object, default to empty object
     */

  }, {
    key: "jsonSuccess",
    value: function jsonSuccess(response) {
      return this.processJson(_objectSpread({
        statusCode: 200
      }, response));
    }
    /**
     * waits for the given time
     */

  }, {
    key: "wait",
    value: function wait(time) {
      var _this5 = this;

      return new Promise(function (resolve) {
        setTimeout(function () {
          resolve(_this5);
        }, time);
      });
    }
    /**
     * it process a json api response, automatically handling
     * the then and catch responses,
     * @param response
     * @returns
     */

  }, {
    key: "processJSONApi",
    value: function () {
      var _processJSONApi = _asyncToGenerator__default['default']( /*#__PURE__*/_regeneratorRuntime__default['default'].mark(function _callee(responsePromise, options) {
        var _this6 = this;

        return _regeneratorRuntime__default['default'].wrap(function _callee$(_context) {
          while (1) {
            switch (_context.prev = _context.next) {
              case 0:
                return _context.abrupt("return", responsePromise.then(function (response) {
                  return _this6.processJson(_objectSpread({
                    statusCode: 200
                  }, response), options);
                })["catch"](function (err) {
                  // handle errors
                  if (err instanceof Error) {
                    return Utils.handleError(err, _this6);
                  }

                  return _this6.processJson(_objectSpread({
                    statusCode: 400
                  }, err), options);
                }));

              case 1:
              case "end":
                return _context.stop();
            }
          }
        }, _callee);
      }));

      function processJSONApi(_x, _x2) {
        return _processJSONApi.apply(this, arguments);
      }

      return processJSONApi;
    }()
  }]);

  return Response;
}(http.ServerResponse);

exports.Response = Response;
//# sourceMappingURL=Response.js.map
