private function parseArguments(callable $call, array $matches) : array
    {
        if (is_object($call) && method_exists($call, '__invoke')) {
            $reflection = new ReflectionMethod($call, '__invoke');
        } elseif (is_array($call) && method_exists($call[0], $call[1])) {
            $reflection = new ReflectionMethod($call[0], $call[1]);
        } else {
            $reflection = new ReflectionFunction($call);
        }
        $parameters = $reflection->getParameters();
        $arguments = [];
        $request = 'Psr\Http\Message\RequestInterface';
        foreach ($parameters as $value) {
            if ($class = $value->getClass()
                and $class->implementsInterface($request)
            ) {
                $arguments[$value->name] = $this->request;
            } elseif ($value->isCallable()) {
                $arguments[$value->name] = isset($this->actions[$value->name]) ?
                    $this->actions[$value->name] :
                    new EmptyResponse(405);
            } else {
                $arguments[$value->name] = null;
            }
        }
        $remove = [];
        $args = isset($matches) ? $matches : [];
        $justMatched = false;
        foreach ($args as $key => $value) {
            if (is_numeric($key) && $justMatched) {
                $remove[] = $key;
            }
            $justMatched = false;
            if (is_string($key) && array_key_exists($key, $arguments)) {
                $arguments[$key] = $value;
                $remove[] = $key;
                $justMatched = true;
            }
        }
        foreach ($remove as $key) {
            unset($args[$key]);
        }
        // For remaining arguments, use the next available index:
        array_walk($arguments, function (&$value) use (&$args) {
            if (is_null($value) && $args) {
                $value = array_shift($args);
            }
        });
        // Remove unset arguments:
        $args = [];
        foreach ($arguments as $arg) {
            if (isset($arg)) {
                $args[] = $arg;
            }
        }
        array_walk($args, function (&$value) {
            if (is_string($value)) {
                $value = preg_replace("@/$@", '', $value);
            }
        });
        return $args;
    }