private function findRoute(array $pathSegments = null) {

	    if(!count($this->routes)) {
	        throw new ApplicationException('Routing aborted: No routes defined.');
        }

		// if no page given try to get the first from list

		if(empty($pathSegments)) {

			return reset($this->routes);
		}

		$pathToCheck	= implode('/', $pathSegments);
		$requestMethod	= Request::createFromGlobals()->getMethod();

		/* @var Route $foundRoute */

		$foundRoute = null;

        /* @var Route $default */

		$default = null;

		// iterate over routes and try to find the "best" match

        /* @var Route $route */

		foreach($this->routes as $route) {

			// keep default route as fallback, when no match is found

			if($route->getRouteId() === 'default') {
				$default = $route;
			}

			// pick route only when request method requirement is met

			if(
				preg_match('~^' . $route->getMatchExpression() . '$~', $pathToCheck) &&
				$route->allowsRequestMethod($requestMethod)
			) {

				// if no route was found yet, pick this first match

				if(!isset($foundRoute)) {
                    $foundRoute = $route;
                    continue;
                }

                // prefer route which is more specific with request methods

                if(count($route->getRequestMethods()) > count($foundRoute->getRequestMethods())) {
                    continue;
                }

                // a route with less (or no) placeholders is preferred over one with placeholders

                if(count($route->getPlaceholderNames()) > count($foundRoute->getPlaceholderNames())) {
                    continue;
                }

                // if a route has been found previously, choose the more "precise" and/or later one
                // choose the route with more satisfied placeholders
                // @todo could be optimized

                $foundRouteSatisfiedPlaceholderCount = count($this->getSatisfiedPlaceholders($foundRoute, $pathToCheck));
                $routeSatisfiedPlaceholderCount = count($this->getSatisfiedPlaceholders($route, $pathToCheck));

                if (
                    ($routeSatisfiedPlaceholderCount - count($route->getPlaceholderNames())) < ($foundRouteSatisfiedPlaceholderCount - count($foundRoute->getPlaceholderNames()))
                ) {
                    continue;
                }
                if (
                    ($routeSatisfiedPlaceholderCount - count($route->getPlaceholderNames())) === ($foundRouteSatisfiedPlaceholderCount - count($foundRoute->getPlaceholderNames())) &&
                    count($route->getPlaceholderNames()) > count($foundRoute->getPlaceholderNames())
                ) {
                    continue;
                }

                $foundRoute = $route;

			}
		}

		// return "normal" route, if found

		if(isset($foundRoute)) {
			return $foundRoute;
		}

		// return default route as fallback (if available)

		return $default;
	}