   (:require [criterium.core :as cc]
             [reitit.perf-utils :refer :all]
             [reitit.ring :as ring]
-            [clojure.string :as str]))
+            [clojure.string :as str]
+            [reitit.core :as r]))
 
 ;;
 ;; start repl with `lein perf repl`

      (mapv (fn [[p d]] (if (= path p) [p (assoc d method h)] [p d])) routes)
      (conj routes [path {method h}]))))

(def routes [{"POST", "/1/classes/:className"},
             {"GET", "/1/classes/:className/:objectId"},
             {"PUT", "/1/classes/:className/:objectId"},
             {"GET", "/1/classes/:className"},
             {"DELETE", "/1/classes/:className/:objectId"},

             ;; Users
             {"POST", "/1/users"},
             {"GET", "/1/login"},
             {"GET", "/1/users/:objectId"},
             {"PUT", "/1/users/:objectId"},
             {"GET", "/1/users"},
             {"DELETE", "/1/users/:objectId"},
             {"POST", "/1/requestPasswordReset"},

             ;; Roles
             {"POST", "/1/roles"},
             {"GET", "/1/roles/:objectId"},
             {"PUT", "/1/roles/:objectId"},
             {"GET", "/1/roles"},
             {"DELETE", "/1/roles/:objectId"},

             ;; Files
             {"POST", "/1/files/:fileName"},

             ;; Analytics
             {"POST", "/1/events/:eventName"},

             ;; Push Notifications
             {"POST", "/1/push"},

             ;; Installations
             {"POST", "/1/installations"},
             {"GET", "/1/installations/:objectId"},
             {"PUT", "/1/installations/:objectId"},
             {"GET", "/1/installations"},
             {"DELETE", "/1/installations/:objectId"},

             ;; Cloud Functions
             {"POST", "/1/functions"}])


(def app

    (ring/router
      (reduce (partial add h) [] routes))))

(defrecord Req [uri request-method])

(defn route->req [route]
  (map->Req {:request-method (-> route keys first str/lower-case keyword)
             :uri (str/replace (-> route vals first) #"\/:\w+" "/1")}))

(defn routing-test []
  ;; https://github.com/julienschmidt/go-http-routing-benchmark
  ;; go test -bench="HttpRouter"

  (suite "httprouter vs reitit-ring")

  ;;  40ns (httprouter)
  ;; 140ns
  (let [req (map->Req {:request-method :get, :uri "/user/repos"})]
      (title "static")
      (assert (= {:status 200, :body "/user/repos"} (app req)))
      (cc/quick-bench (app req)))

  ;; 160ns (httprouter)
  ;; 990ns
  (let [req (map->Req {:request-method :get, :uri "/repos/julienschmidt/httprouter/stargazers"})]
      (title "param")
      (assert (= {:status 200, :body "/repos/:owner/:repo/stargazers"} (app req)))
      (cc/quick-bench (app req)))

  ;;  30µs (httprouter)
  ;; 190µs
  (let [requests (mapv route->req routes)]
    (title "all")
    (cc/quick-bench
      (doseq [r requests]
        (app r)))))

(comment
  (routing-test))
