(ns routes.__table__
  (:require [coast]
            [components :refer :all]))


(defn assoc-__table__ [handler]
  (fn [request]
    (let [{:keys [db params]} request
          id (get params :id)
          __table__ (coast/fetch db [:__table__ id])]
      (handler (assoc request :__table__ __table__ :id id)))))


(def params
  (coast/params :__table__
    [:required [__keywords__]]))


(defn index [request]
  (let [{:keys [db]} request
        rows (coast/fetch db [:__table__])]
    (container
      (vstack {:spacing "m"}
        (link-to [::build] "New __table__")

        (when (not (empty? rows))
          (table
            (thead
              (tr
                __table-headers__))
            (tbody
              (for [row rows]
                (tr
                  __table-data__
                  (td
                    (link-to [::show row] "Show"))
                  (td
                    (link-to [::edit row] "Edit"))
                  (td
                    (button-to [::delete row] {:data-confirm "Are you sure?"} "Delete")))))))))))


(defn show [request]
  (let [__table__ (get request :__table__)]
    (container
      (vstack {:spacing "m"}
        (dl
          __data-elements__)
        (link-to [::index] "List")
        (link-to [::edit __table__] "Edit")
        (button-to [::delete __table__] {:data-confirm "Are you sure?"}
          "Delete")))))


(defn build [request]
  (let [errors (get request :errors)]
   (container {:class "mw6"}
    (vstack {:spacing "m"}
      (form-for [::create]
        __form-elements__

        (link-to [::index] "Cancel")
        (submit "New __table__"))))))


(defn create [request]
  (let [{:keys [db]} request
        [_ errors] (->> (params request)
                        (coast/insert db)
                        (coast/rescue))]
    (if (nil? errors)
      (coast/redirect-to ::index)
      (build (assoc request :errors errors)))))


(defn edit [request]
  (let [{:keys [__table__ errors]} request]
    (container {:class "mw6"}
      (vstack {:spacing "m"}
        (form-for [::patch __table__]
          __edit-elements__

          (link-to [::index] "Cancel")
          (submit "Update __table__"))))))


(defn patch [request]
  (let [{:keys [db id]} request
        [_ errors] (as-> (params request) %
                         (coast/update db % {:id id})
                         (coast/rescue %))]
    (if (nil? errors)
      (coast/redirect-to ::index)
      (edit (assoc request :errors errors)))))


(defn delete [request]
  (let [{:keys [db id]} request
        deleted (coast/delete db {:__table__ {:id id}})]
    (if (empty? deleted)
      (-> (coast/redirect-to ::index)
          (coast/flash "Something went wrong!"))
      (coast/redirect-to ::index))))


(def routes
  (coast/routes
    [:get "/__table__" index]
    [:get "/__table__/build" build]
    [:post "/__table__" create]

    (coast/middleware assoc-__table__
      [:get "/__table__/:id" show]
      [:get "/__table__/:id/edit" edit]
      [:patch "/__table__/:id" patch]
      [:delete "/__table__/:id" delete])))
