'use strict';

function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; }

var _classCallCheck = _interopDefault(require('@babel/runtime/helpers/classCallCheck'));
var _createClass = _interopDefault(require('@babel/runtime/helpers/createClass'));
var _defineProperty = _interopDefault(require('@babel/runtime/helpers/defineProperty'));
var utils = require('@forensic-js/utils');
var Wrapper = _interopDefault(require('./Wrapper'));
var nodeUtils = require('@forensic-js/node-utils');
var Constants = require('./Constants');

var Router =
/*#__PURE__*/
function () {
  /**
   *
   * @param inheritMiddlewares - boolean indicating if parent middlewares should be inherited.
   */
  function Router(inheritMiddlewares) {
    _classCallCheck(this, Router);

    _defineProperty(this, "basePath", '');

    _defineProperty(this, "routes", {
      options: [],
      head: [],
      get: [],
      post: [],
      put: [],
      delete: [],
      all: []
    });

    _defineProperty(this, "middlewares", []);

    _defineProperty(this, "inheritMiddlewares", void 0);

    this.inheritMiddlewares = inheritMiddlewares;
  }
  /**
   * resolves the url route by joining it to the base path
   */


  _createClass(Router, [{
    key: "resolveUrl",
    value: function resolveUrl(url) {
      url = nodeUtils.joinPaths(this.basePath, utils.stripSlashes(url));
      return url !== '.' ? url : '';
    }
    /**
     * sets the route rule for a given http method
     *
     * @param method - the http method
     * @param url - route url
     * @param callback - route callback handler
     * @param options - route configuration object or middleware or array of middlewares
     */

  }, {
    key: "set",
    value: function set(method, url, callback, options) {
      var resolvedOptions = utils.isUndefined(options) ? null : {
        middleware: utils.isObject(options) ? utils.makeArray(options.middleware) : utils.makeArray(options)
      };
      var routeId = Constants.assignRouteId();
      this.routes[method].push([routeId, this.resolveUrl(url), callback, resolvedOptions]);
      return routeId;
    }
    /**
     * returns the routes.
     */

  }, {
    key: "getRoutes",
    value: function getRoutes() {
      return this.routes;
    }
    /**
     * returns the middlewares
     */

  }, {
    key: "getMiddlewares",
    value: function getMiddlewares() {
      return this.middlewares;
    }
    /**
     * returns routing base path that gets prepended to all route and middleware urls
     */

  }, {
    key: "getBasePath",
    value: function getBasePath() {
      return this.basePath;
    }
    /**
     * sets routing base path that gets prepended to all route and middleware urls
     */

  }, {
    key: "setBasePath",
    value: function setBasePath(basePath) {
      this.basePath = utils.stripSlashes(basePath);
      return this;
    }
    /**
     * stores route rules for http OPTIONS method
     *
     * @param url - route url
     * @param callback - route callback handler
     * @param options - route configuration object or middleware or array of middlewares
     */

  }, {
    key: "options",
    value: function options(url, callback, _options) {
      return this.set('options', url, callback, _options);
    }
    /**
     * stores route rules for http HEAD method
     *
     * @param url - route url
     * @param callback - route callback handler
     * @param options - route configuration object or middleware or array of middlewares
     */

  }, {
    key: "head",
    value: function head(url, callback, options) {
      return this.set('head', url, callback, options);
    }
    /**
     * stores route rules for http GET method
     *
     * @param url - route url
     * @param callback - route callback handler
     * @param options - route configuration object or middleware or array of middlewares
     */

  }, {
    key: "get",
    value: function get(url, callback, options) {
      return this.set('get', url, callback, options);
    }
    /**
     * stores route rules for http POST method
     *
     * @param url - route url
     * @param callback - route callback handler
     * @param options - route configuration object or middleware or array of middlewares
     */

  }, {
    key: "post",
    value: function post(url, callback, options) {
      return this.set('post', url, callback, options);
    }
    /**
     * stores route rules for http PUT method
     *
     * @param url - route url
     * @param callback - route callback handler
     * @param options - route configuration object or middleware or array of middlewares
     */

  }, {
    key: "put",
    value: function put(url, callback, options) {
      return this.set('put', url, callback, options);
    }
    /**
     * stores route rules for http DELETE method
     *
     * @param url - route url
     * @param callback - route callback handler
     * @param options - route configuration object or middleware or array of middlewares
     */

  }, {
    key: "delete",
    value: function _delete(url, callback, options) {
      return this.set('delete', url, callback, options);
    }
    /**
     * stores route rules for all http methods
     *
     * @param url - route url
     * @param callback - route callback handler
     * @param options - route configuration object or middleware or array of middlewares
     */

  }, {
    key: "all",
    value: function all(url, callback, options) {
      return this.set('all', url, callback, options);
    }
    /**
     * creates and returns a route wrapper for the given url
     */

  }, {
    key: "route",
    value: function route(url) {
      return new Wrapper(this, url);
    }
    /**
     * registers a middleware to be called whenever the given url is visited
     *
     * @param url - url to apply middleware to. use * to appy to all urls
     * @param middleware - the middleware or array of middlewares
     * @param options - middleware configuration option. here, you can specify the http method
     * that the middleware will run against
     *@returns {MiddlewareId} returns the middleware id, can be used to delete the middleware.
     */

  }, {
    key: "use",
    value: function use(url, middleware, options) {
      middleware = utils.makeArray(middleware);
      var resolvedOptions = utils.isUndefined(options) ? null : {
        method: utils.isObject(options) ? utils.makeArray(options.method) : utils.makeArray(options)
      };
      var middlewareId = Constants.assignMiddlewareId();
      this.middlewares.push([middlewareId, this.resolveUrl(url), middleware, resolvedOptions]);
      return middlewareId;
    }
    /**
     * returns a boolean indicating if router inherits parent's middlewares when mounted
     * @param status - if given, it sets this value
     */

  }, {
    key: "shouldInheritMiddlewares",
    value: function shouldInheritMiddlewares(status) {
      if (utils.isBoolean(status)) {
        this.inheritMiddlewares = status;
      }

      return this.inheritMiddlewares;
    }
    /**
     * removes a given route
     * @param id route id
     */

  }, {
    key: "removeRoute",
    value: function removeRoute(id) {
      var findIndex = function findIndex(routeInstance) {
        return routeInstance[0] === id;
      };

      var keys = Object.keys(this.routes);

      for (var _i = 0, _keys = keys; _i < _keys.length; _i++) {
        var key = _keys[_i];
        var route = this.routes[key];
        var index = route.findIndex(findIndex);

        if (index !== -1) {
          route.splice(index, 1);
          return true;
        }
      }

      return false;
    }
    /**
     * removes a given middleware. returns true if it succeeds, otherwise, it returns false
     * @param id middleware id
     */

  }, {
    key: "removeMiddleware",
    value: function removeMiddleware(id) {
      var findIndex = function findIndex(middlewareInstance) {
        return middlewareInstance[0] === id;
      };

      var middlewares = this.middlewares;
      var index = middlewares.findIndex(findIndex);

      if (index !== -1) {
        middlewares.splice(index, 1);
        return true;
      }

      return false;
    }
  }]);

  return Router;
}();

module.exports = Router;
//# sourceMappingURL=Router.js.map
