(ns wanijo.infrastructure.routing
  (:require [clojure.string :as string]))

(def all-routes
  (atom {}))

(defn register! [id path]
  (swap! all-routes
         assoc id path)
  path)

(defn check-params [path params]
  (when (nil? path)
    (throw
     (ex-info
      "Path is not registered"
      {:path path
       :params params})))
  (let [matcher (re-matcher #":[^/]+" path)
        matches (take-while some? (repeatedly #(re-find matcher)))]
    (doseq [match matches
            :let [kwparam (keyword (subs match 1))
                  exists? (contains? params kwparam)]]
      (when-not exists?
        (throw
         (ex-info
          (str "Key '" kwparam
               "' does not exist in parameter map for path "
               path)
          {:path path
           :params params}))))))

(defn parse-path [path params]
  (check-params path params)
  (reduce-kv
   (fn [new-path param-id param-value]
     (string/replace
      new-path
      (str ":" (name param-id))
      (str param-value)))
   path
   params))

(defn path
  ([id]
   (path id {}))
  ([id params]
   (let [path (id @all-routes)]
     (parse-path path params))))
