             [meetdown.data :as data]
             [org.httpkit.server :refer [run-server]]
             [taoensso.timbre :as timbre]
-            [meetdown.auth :as auth]))
+            [meetdown.auth :as auth]
+            [ring.util.response :refer [response status]]))
+
+(defn wrap-assert-logged-in [handler]
+  (fn [{:keys [user-id] :as req}]
+    (if user-id
+      (handler req)
+
+      (-> (response :unauthenticated)
+          (status 401)))))
+
+(defn wrap-assert-user-roles [handler user-roles]
+  (fn [{req-user-roles :user-roles, :as req}]
+    (if (empty? (set/difference (set user-roles) (set req-user-roles)))
+      (handler req)
+
+      (-> (response :forbidden)
+          (status 403)))))
 
 (def auth-handlers
   ;; Auth: test with:


  ;; curl -iXPOST http://localhost:3000/q -d "{:type :get-current-user}" -H "Content-Type: application/edn" -H "Authorization: <token>"

  {:get-current-user {:handler (fn [{:keys [db body-params user-id user-roles]}]
                                 (when user-id
                                   {:body {:user-id user-id
                                           :user-roles user-roles}}))
                      :user-roles #{:admin}}

   ;; yes, we log *anyone* in...
   :login {:handler (fn [{:keys [db body-params]}]
                       {:body :logged-in
                        :headers {"Authorization" (auth/generate-token {:user-id (:user-id body-params)
                                                                        :user-roles #{:admin}})}})}})

(def event-handlers
  {:get-events {:handler (fn [{:keys [db body-params]}]
                           {:body (data/get-events db)})}

   :create-event {:handler (fn [{:keys [db db-conn body-params]}]
                             {:body {:db/id (:db/id (data/create-entity db-conn (:txn-data body-params)))}})}

   :get-event {:handler (fn [{:keys [db body-params]}]
                          {:body (->> (get-in body-params [:txn-data :db/id])
                                      (data/to-ent db))})}})

(def user-handlers
  {:create-user {:handler (fn [{:keys [db db-conn body-params]}]
                            {:body {:db/id (:db/id (data/create-entity db-conn (:txn-data body-params)))}})}})

(def all-handlers
  (merge auth-handlers event-handlers user-handlers))

(defn- handle-query [req]
  (let [req-type (get-in req [:body-params :type])]
    (if-let [handler (get-in all-handlers
                             [req-type :handler])]
      (handler req)
      {:status 415 :body (str "Unsupported type - " req-type)})))


(ns meetdown.http
  (:require [org.httpkit.server :as http]
            [com.stuartsierra.component :as component]
            [clojure.set :as set]
            [compojure.core :refer [routes GET POST DELETE ANY context]]
            [compojure.route :refer [resources files]]
            [hiccup.core :refer [html]]
