           [:span.caret]]
          [:ul.dropdown-menu
           {:role "menu"}
-          (map (fn [entity-key]
-                 [:li (link-to (<< "/~(name entity-key)") (string/capitalize (dog-mission/translate entity-key)))])
-               (entity-keys))]]]]]]
+          (map (fn [entity-class-key]
+                 [:li (link-to (<< "/~(name entity-class-key)") (string/capitalize (dog-mission/translate entity-class-key)))])
+               (entity-class-keys))]]]]]]
     [:article
      [:div.container-fluid
       contents]]


;; Models.

(defn entity-keys
  []
  (keys @database-schema))

(defn entity-schema
  [entity-key]
  (get @database-schema entity-key))

(defn property-keys
  ([entity-key & property-types]
   (->> (entity-schema entity-key)
        ((apply juxt property-types))
        (map keys)
        (apply concat)))
  ([entity-key]
   (property-keys entity-key :columns :many-to-one-relationships :one-to-many-relationships)))

(defn inputtable-property-keys
  [entity-key]
  (property-keys entity-key :columns :many-to-one-relationships))

(defn search-condition-property-keys
  [entity-key]
  (or (get-in (entity-schema entity-key) [:search-condition :properties])
      (inputtable-property-keys entity-key)))

(defn list-property-keys
  [entity-key]
  (or (get-in (entity-schema entity-key) [:list :properties])
      (property-keys entity-key)))

(defn sort-keyfn-and-comp
  [entity-key]
  (let [[keyfn comp] (get-in (entity-schema entity-key) [:list :sort-by])]
    [(or keyfn (first (list-property-keys entity-key)))
     (or comp  compare)]))

(defn representative-property-key
  [entity-key]
  (or (:representative (entity-schema entity-key))
      :name))

(defn property-schema
  [entity-key property-key]
  (let [entity-schema (entity-schema entity-key)]
    (or (get-in entity-schema [:columns                   property-key])
        (get-in entity-schema [:many-to-one-relationships property-key])
        (get-in entity-schema [:one-to-many-relationships property-key]))))

(defn placeholder
  [entity-key property-key]
  (get-in (entity-schema entity-key) [:placeholders property-key]))

(defn property-type
  [entity-key property-key]
  (let [entity-schema (entity-schema entity-key)]
    (or (get-in entity-schema [:columns property-key :type])
        (and (get-in entity-schema [:many-to-one-relationships property-key]) :many-to-one)
        (and (get-in entity-schema [:one-to-many-relationships property-key]) :one-to-many))))

(defmulti parse-property-param
  (fn [entity-key property-key param-value] (property-type entity-key property-key)))

(defmethod parse-property-param :integer
  [_ _ param-value]

     (label param-key-key (string/capitalize (dog-mission/translate param-key)))
     (hidden-field param-key-key (get entity (many-to-one-relationship-key-to-physical-column-key property-key)))
     [:div.input-group
      (text-field {:class "form-control", :readonly "readonly"} param-key-name-key (format-property-param entity-class-key property-key (get entity property-key)))
      [:span.input-group-addon {:data-open-window-uri (to-uri (<< "/~(name (:table-key (property-schema entity-class-key property-key)))/select?target-element-id=~(URLEncoder/encode (name param-key-key))"))}
       [:span.glyphicon.glyphicon-search]]]]))

(defmethod input-control :one-to-many
  [entity-class-key entity property-key]
  (let [param-key (param-key entity-class-key property-key)]
    [:div.form-group
     (label param-key (string/capitalize (dog-mission/translate param-key)))
     (text-field {:class "form-control", :disabled "disabled"} param-key (format-property-param entity-class-key property-key (get entity property-key)))]))

(defmethod input-control :default
  [entity-class-key entity property-key]
  nil)

(defn input-form-panel
  [entity-class-key entity method uri submit-button-caption]
  (form-to
   [method uri]
   (hidden-field :index-params (get-in *request* [:params :index-params]))
   (map (partial input-control entity-class-key entity) (property-keys entity-class-key))
   [:p
    (submit-button {:class "btn btn-primary"} (string/capitalize (dog-mission/translate submit-button-caption)))
    "&nbsp;"
    (link-to-with-method-and-params {:class "btn btn-default"} (<< "/~(name entity-class-key)") :get (base64-decode (get-in *request* [:params :index-params])) (string/capitalize (dog-mission/translate :back)))]))

;; views.

(defn list-entities-panel
  [entity-class-key entities page-count page entity-command-fn command-fn]
  (if entities
    (list [:table.table.table-condensed.table-hover
           [:thead
            [:tr
             (map (fn [property-key]
                    [:th (string/capitalize (dog-mission/translate (param-key entity-class-key property-key)))])
                  (list-property-keys entity-class-key))
             [:th]]]
           [:tbody
            (map (fn [entity]
                   [:tr
                    (map (fn [property-key]
                           [:td
                            [:div (format-property-param entity-class-key property-key (get entity property-key))]])
                         (list-property-keys entity-class-key))
                    [:td.command-cell
                     (entity-command-fn entity)]])
                 entities)]]
