             [clojure.string :as string]
             [clojure.set :as set]
             [io.aviso.tracker :as t]
-            [io.aviso.rook.internals :as internals]
+            [io.aviso.rook.internals :as internals :refer [consume]]
             [clojure.string :as str]
             [clojure.tools.logging :as l]
             [io.aviso.rook.utils :as utils]))

  (let [arg-symbol (symbol-for-argument arg)
        arg-meta (meta arg-symbol)]
    (t/track #(format "Identifying argument resolver for `%s'." arg-symbol)
      (cond
        ;; route param resolution takes precedence
        (contains? route-params arg)
        (make-route-param-resolver arg-symbol)

        ;; explicit ::rook/resolver metadata takes precedence for non-route params
        (contains? arg-meta :io.aviso.rook/resolver)
        (find-resolver arg-resolvers arg-symbol (:io.aviso.rook/resolver arg-meta))

        :else
        (if-let [resolver-tag (find-argument-resolver-tag
                                arg-resolvers arg-symbol arg-meta)]
          ;; explicit tags attached to the arg symbol itself come next
          (find-resolver arg-resolvers arg-symbol resolver-tag)

          ;; non-route-param name-based resolution is implicit and
          ;; should not override explicit tags, so this check comes
          ;; last; NB. the value at arg-symbol might be a keyword
          ;; identifying a resolver factory, so we still need to call
          ;; find-resolver
          (if (contains? arg-resolvers arg-symbol)
            (find-resolver arg-resolvers arg-symbol (get arg-resolvers arg-symbol))

            ;; only static resolution is supported
            (throw (ex-info
                     (format "Unable to identify argument resolver for symbol `%s'." arg-symbol)
                     {:symbol        arg-symbol
                      :symbol-meta   arg-meta
                      :route-params  route-params
                      :arg-resolvers arg-resolvers}))))))))

(defn- create-arglist-resolver
  "Returns a function that is passed the Ring request and returns an array of argument values which

  entries such as

      [:get [\"api\" \"foo\"] 'example.foo/index ns-middleware]."
  {:arglists '([options ns-specs]
               [ns-specs])}
  [& arguments]
  (consume arguments
    [options map? :?
     ns-specs :&]
    (let [{outer-context-pathvec :context-pathvec
           default-middleware    :default-middleware} (merge default-opts options)
          ns-specs' (canonicalize-ns-specs
                      []
                      default-middleware
                      ns-specs)]
      [(reduce into [outer-context-pathvec default-middleware]
               (map (fn [[context-pathvec ns-sym middleware]]
                      (simple-namespace-dispatch-table
                        context-pathvec ns-sym middleware))
                    ns-specs'))])))
