 
 (defn make-content-type-weigher
   [req k]
-  (let [accepts (->> (get-in req [:headers "accept"]) parse-csv (map mime/string->media-type)
-                     (sort-by :weight (comp - compare)))]
-    (->
-     (fn [rep]
-       (some (partial content-type-acceptable? (:content-type rep)) accepts))
-     (wrap-weigher :content-type)
-     skip-rejected)))
+  (->
+   (->> (get-in req [:headers "accept"]) parse-csv (map mime/string->media-type)
+        (sort-by :weight (comp - compare)))
+   best-content-type-acceptable?
+   (wrap-weigher :content-type)
+   skip-rejected))
 
-;; Add lots of tests for this
+(defn get-content-type-weight
+  "Given the request and a representation, get the weight of the representation."
+  [req rep]
+  (let [k :content-type
+        weigher-fn (make-content-type-weigher req k)
+        rep (weigher-fn rep)]
+    (or (get-in rep [:weights k])
+        (when (:rejected rep) :rejected))))
 
 (deftest content-type-test
-  (let [req {:headers {"accept" "text/xml;q=0.8"}}
-        f (make-content-type-weigher req :content-type)]
+  ;; Basic match
+  (is (= (get-content-type-weight
+          {:headers {"accept" "text/html"}}
+          {:content-type (mime/string->media-type "text/html")})
+         [(float 1.0) 3 0 (float 1.0)]))
 
-    (is (= (get-in (f {:content-type (mime/string->media-type "text/xml")})
-                   [:weights :content-type])
-           [(float 0.8) 3 0 (float 1.0)]))))
+  ;; Basic match, with multiple options
+  (is (= (get-content-type-weight
+          {:headers {"accept" "image/png,text/html"}}
+          {:content-type (mime/string->media-type "text/html")})
+         [(float 1.0) 3 0 (float 1.0)]))
+
+  ;; Basic reject
+  (is (= (get-content-type-weight
+          {:headers {"accept" "text/html"}}
+          {:content-type (mime/string->media-type "text/plain")})
+         :rejected))
+
+  ;; Basic reject with multiple options
+  (is (= (get-content-type-weight
+          {:headers {"accept" "image/png,text/html"}}
+          {:content-type (mime/string->media-type "text/plain")})
+         :rejected))
+
+  ;; Wildcard match
+  (is (= (second (get-content-type-weight
+                  {:headers {"accept" "image/png,text/*"}}
+                  {:content-type (mime/string->media-type "text/html")}))
+         ;; We get a match with a specificty score of 2
+         2))
+
+  ;; Specific match beats wildcard
+  (is (= (second (get-content-type-weight
+                  {:headers {"accept" "image/png,text/*,text/html"}}
+                  {:content-type (mime/string->media-type "text/html")}))
+         ;; We get a specificty score of 3, indicating we matched on the
+         ;; text/html rather than the preceeding text/*
+         3))
+
+  ;; TODO: More tests
+  )
 
 ;; "A request without any Accept header
 ;; field implies that the user agent

   [yada.util :refer (parse-csv)]
   [yada.negotiation :as negotiation]))


(defn content-type-acceptable?
  "Compare a single acceptable mime-type (extracted from an Accept

      (and (= (mime/media-type acceptable) "*/*"))
      [(:weight acceptable) 1 (count (:parameters candidate)) (:weight candidate)])))

(defn best-content-type-acceptable? [accepts]
  (fn [rep]
    (best-by identity (map (partial content-type-acceptable? (:content-type rep)) accepts))))

(defn skip-rejected [f]
  (fn [rep]
    (if (:rejected rep) rep (f rep))))
