                    [schema.macros :as sm])
   (:import [goog.history EventType Html5History]))
 
+;; ## Helpers
+
+(defn example
+  ([item] (d/div {:class "bs-example"} item))
+  ([props item]
+     (d/div (u/merge-props props {:class "bs-example"})
+            item)))
+
 ;; ## Button Examples
 
 (defn button-example []
-  (b/toolbar {}
-             (b/button {} "Default")
-             (b/button {:bs-style "primary"} "Primary")
-             (b/button {:bs-style "success"} "Success")
-             (b/button {:bs-style "info"} "Info")
-             (b/button {:bs-style "warning"} "Warning")
-             (b/button {:bs-style "danger"} "Danger")
-             (b/button {:bs-style "link"} "Link")))
+  (example
+   (b/toolbar {}
+              (b/button {} "Default")
+              (b/button {:bs-style "primary"} "Primary")
+              (b/button {:bs-style "success"} "Success")
+              (b/button {:bs-style "info"} "Info")
+              (b/button {:bs-style "warning"} "Warning")
+              (b/button {:bs-style "danger"} "Danger")
+              (b/button {:bs-style "link"} "Link"))))
 
 (defn button-sizing []
-  (d/div
-   (b/toolbar {}
-              (b/button {:bs-style "primary" :bs-size "large"} "Large button")
-              (b/button {:bs-size "large"} "Large button"))
-   (b/toolbar {}
-              (b/button {:bs-style "primary" :bs-size "large"} "Default button")
-              (b/button {:bs-size "large"} "Large button"))
-   (b/toolbar {}
-              (b/button {:bs-style "primary" :bs-size "large"} "Small button")
-              (b/button {:bs-size "large"} "Large button"))
-   (b/toolbar {}
-              (b/button {:bs-style "primary" :bs-size "xsmall"}
-                        "Extra small button")
-              (b/button {:bs-size "large"} "Large button"))))
+  (example
+   [(b/toolbar {}
+                (b/button {:bs-style "primary" :bs-size "large"} "Large button")
+                (b/button {:bs-size "large"} "Large button"))
+    (b/toolbar {}
+               (b/button {:bs-style "primary"} "Default button")
+               (b/button {} "Default button"))
+    (b/toolbar {}
+               (b/button {:bs-style "primary" :bs-size "small"} "Small button")
+               (b/button {:bs-size "small"} "Small button"))
+    (b/toolbar {}
+               (b/button {:bs-style "primary" :bs-size "xsmall"} "Extra small button")
+               (b/button {:bs-size "xsmall"} "Extra small button"))]))
 
 (defn button-block []
   (d/div
-   (d/h3 "Button Examples")
+   (d/h1 {:id "buttons" :class "page-header"} "Buttons " (d/small "Button"))
+   (d/h2 {:id "button-options"} "Options")c
+
+   (d/p "Use any of the available button style types to quickly create a styled button. Just modify the " (d/code ":bs-style" ) " prop.")
    (button-example)
-   (d/h3 "Button Sizing")
+   (d/div {:class "bs-callout bs-callout-warning"}
+          (d/h4 "Button Spacing")
+          (d/p "Because React doesn't output newlines between elements, buttons on the same line are displayed flush against each other. To preserve the spacing between multiple inline buttons, wrap your button group in " (d/code "b/toolbar") "."))
+   (d/h2 "Sizes")
+   (d/p "Fancy larger or smaller buttons? Add "
+        (d/code ":bs-size large") ", "
+        (d/code ":bs-size small") ", or "
+        (d/code ":bs-size xsmall") " for additional sizes.")
    (button-sizing)
    (d/p "Create block level buttons—those that span the full width of a parent— by adding the block prop.")
-   (d/div {:class "well"
-           :style {:max-width 400
-                   :margin "0 auto 10px"}}
-          (b/button {:bs-style "primary" :bs-size "large" :block? true}
-                    "Block level button")
-          (b/button {:bs-size "large" :block? true}
-                    "Block level button"))
+   (example
+    (d/div {:class "well"
+            :style {:max-width 400
+                    :margin "0 auto 10px"}}
+           (b/button {:bs-style "primary" :bs-size "large" :block? true}
+                     "Block level button")
+           (b/button {:bs-size "large" :block? true}
+                     "Block level button")))
    (d/p "To set a buttons active state simply set the components active prop.")
-   (b/toolbar {}
-              (b/button {:bs-style "primary" :bs-size "large" :active? true}
-                        "Primary button")
-              (b/button {:bs-size "large" :bs-style "default" :active? true}
-                        "Button"))
+   (example
+    (b/toolbar {}
+               (b/button {:bs-style "primary" :bs-size "large" :active? true}
+                         "Primary button")
+               (b/button {:bs-size "large" :bs-style "default" :active? true}
+                         "Button")))
    (d/p "Make buttons look unclickable by fading them back 50%. To do
    this add the disabled attribute to buttons.")
-   (b/toolbar {}
-              (b/button {:bs-style "primary" :bs-size "large" :disabled? true}
-                        "Primary button")
-              (b/button {:bs-size "large" :bs-style "default" :disabled? true}
-                        "Button"))
+   (example
+    (b/toolbar {}
+               (b/button {:bs-style "primary" :bs-size "large" :disabled? true}
+                         "Primary button")
+               (b/button {:bs-size "large" :bs-style "default" :disabled? true}
+                         "Button")))
    (d/h3 "Button Groups")
    (d/p "Wrap a series of buttons in a button group.")
-   (b/button-group {}
-                   (b/button {} "Left")
-                   (b/button {} "Middle")
-                   (b/button {} "Right"))
+   (example
+    (b/button-group {}
+                    (b/button {} "Left")
+                    (b/button {} "Middle")
+                    (b/button {} "Right")))
    (d/p "Combine sets of buttongroups into a button toolbar for more
    complex components.")
-   (b/toolbar {}
-              (b/button-group {} (for [i (range 4)]
-                                   (b/button {} (str (inc i)))))
-              (b/button-group {} (for [i (range 4 7)]
-                                   (b/button {} (str (inc i)))))
-              (b/button-group {} (b/button {} 8)))
+   (example
+    (b/toolbar {}
+               (b/button-group {} (for [i (range 4)]
+                                    (b/button {} (str (inc i)))))
+               (b/button-group {} (for [i (range 4 7)]
+                                    (b/button {} (str (inc i)))))
+               (b/button-group {} (b/button {} 8))))
 
    (d/p "Instead of applying button sizing props to every button in a group, just add bs-size prop to the <ButtonGroup />.")
-   (let [buttons (for [s ["Left" "Middle" "Right"]]
-                   (b/button {} s))]
-     (b/toolbar {}
-                (b/toolbar {} (b/button-group {:bs-size "large"} buttons))
-                (b/toolbar {} (b/button-group {} buttons))
-                (b/toolbar {} (b/button-group {:bs-size "small"} buttons))
-                (b/toolbar {} (b/button-group {:bs-size "xsmall"} buttons))))))
+   (example
+    (let [buttons (for [s ["Left" "Middle" "Right"]]
+                    (b/button {} s))]
+      (b/toolbar {}
+                 (b/toolbar {} (b/button-group {:bs-size "large"} buttons))
+                 (b/toolbar {} (b/button-group {} buttons))
+                 (b/toolbar {} (b/button-group {:bs-size "small"} buttons))
+                 (b/toolbar {} (b/button-group {:bs-size "xsmall"} buttons)))))))
 
 ;; ## Panel Examples
 
 (defn panel-example []
   (d/div
    (d/p "By default, all the <Panel /> does is apply some basic border and padding to contain some content.")
-   (p/panel {} "Basic panel example.")
+   (example
+    (p/panel {} "Basic panel example."))
    (d/p "Easily add a heading container to your panel with the header prop.")
-   (p/panel {:header "Panel heading without title"}
-            "Panel content")
-   (p/panel {:header (d/h3 "Panel title")}
-            "Panel content")
+   (example
+    [(p/panel {:header "Panel heading without title"}
+              "Panel content")
+     (p/panel {:header (d/h3 "Panel title")}
+              "Panel content")])
    (d/p "Pass buttons or secondary text in the footer prop. Note that panel footers do not inherit colors and borders when using contextual variations as they are not meant to be in the foreground.")
-   (p/panel {:footer "Panel footer"} "Panel content")
+   (example
+    (p/panel {:footer "Panel footer"} "Panel content"))
    (d/p "Like other components, easily make a panel more meaningful to a particular context by adding a :bs-style prop.")
-   (for [style [nil "primary" "success" "info" "warning" "danger"]]
-     (p/panel (merge {:header (d/h3 "Panel title")}
-                     (when style {:bs-style style}))
-              "Panel content"))))
+   (example
+    (for [style [nil "primary" "success" "info" "warning" "danger"]]
+      (p/panel (merge {:header (d/h3 "Panel title")}
+                      (when style {:bs-style style}))
+               "Panel content")))))
 
 ;; ## Jumbotron Examples
 
 (defn jumbotron-example []
-  (r/jumbotron {}
-               (d/h1 "Hello, World!")
-               (d/p "This is a simple hero unit, a simple jumbotron-style component for calling extra attention to featured content or information.")
-               (d/p (b/button {:bs-style "primary"} "Learn More"))))
+  (example
+   (r/jumbotron {}
+                (d/h1 "Hello, World!")
+                (d/p "This is a simple hero unit, a simple jumbotron-style component for calling extra attention to featured content or information.")
+                (d/p (b/button {:bs-style "primary"} "Learn More")))))
 
 ;; ## Label Examples
 
 (defn label-examples []
-  (d/div
-   (d/h1 "Label " (r/label {} "New"))
-   (d/h2 "Label " (r/label {} "New"))
-   (d/h3 "Label " (r/label {} "New"))
-   (d/h4 "Label " (r/label {} "New"))
-   (d/h5 "Label " (r/label {} "New"))
-   (d/p "Label " (r/label {} "New"))))
+  (example
+   (d/div
+    (d/h1 "Label " (r/label {} "New"))
+    (d/h2 "Label " (r/label {} "New"))
+    (d/h3 "Label " (r/label {} "New"))
+    (d/h4 "Label " (r/label {} "New"))
+    (d/h5 "Label " (r/label {} "New"))
+    (d/p "Label " (r/label {} "New")))))
 
 (defn label-variations []
-  (d/div
-   (r/label {:bs-style "default"} "Default")
-   (r/label {:bs-style "primary"} "Primary")
-   (r/label {:bs-style "success"} "Success")
-   (r/label {:bs-style "info"} "Info")
-   (r/label {:bs-style "warning"} "Warning")
-   (r/label {:bs-style "danger"} "Danger")))
+  (example
+   [(r/label {:bs-style "default"} "Default")
+    (r/label {:bs-style "primary"} "Primary")
+    (r/label {:bs-style "success"} "Success")
+    (r/label {:bs-style "info"} "Info")
+    (r/label {:bs-style "warning"} "Warning")
+    (r/label {:bs-style "danger"} "Danger")]))
 
 ;; ## Well Examples
 
 (def default-well
-    (r/well {} "Look, I'm in a well!"))
+  (example
+   (r/well {} "Look, I'm in a well!")))
 
 (def optional-well-classes
-  (d/div
-   (r/well {:bs-size "large"} "Look, I'm in a large well!")
-   (r/well {:bs-size "small"} "Look, I'm in a small well!")))
+  (example
+   [(r/well {:bs-size "large"} "Look, I'm in a large well!")
+    (r/well {:bs-size "small"} "Look, I'm in a small well!")]))
 
 ;; ## Page Header
 
 (def header-example
-  (r/page-header {} "Example page header "
-                 (d/small "Subtext for header")))
+  (example
+   (r/page-header {} "Example page header "
+                  (d/small "Subtext for header"))))
 
 ;; ## Grid
 
 (def grid-example
   ;; Clearly this doesn't give me the coloring I need, but it's a
   ;; start toward what the bootstrap docs page gives me.
-  (d/div {:class "bs-example grids-examples"}
-         (g/grid {}
-                 (g/row {:class "show-grid"}
-                        (g/col {:xs 12 :md 8}
-                               (d/code {} "(g/col {:xs 12 :md 8})"))
-                        (g/col {:xs 6 :md 4}
-                               (d/code {} "(g/col {:xs 6 :md 4})")))
-                 (g/row {:class "show-grid"}
-                        (g/col {:xs 6 :md 4}
-                               (d/code {} "(g/col {:xs 6 :md 4})"))
-                        (g/col {:xs 6 :md 4}
-                               (d/code {} "(g/col {:xs 6 :md 4})"))
-                        (g/col {:xs 6 :md 4}
-                               (d/code {} "(g/col {:xs 6 :md 4})")))
-                 (g/row {:class "show-grid"}
-                        (g/col {:xs 6 :xs-offset 6}
-                               (d/code {} "(g/col {:xs 6 :xs-offset 6})")))
-                 (g/row {:class "show-grid"}
-                        (g/col {:md 6 :md-push 6}
-                               (d/code {} "(g/col {:md 6 :md-push 6})"))
-                        (g/col {:md 6 :md-pull 6}
-                               (d/code {} "(g/col {:md 6 :md-push 6})"))))))
+  (example {:class "grids-examples"}
+           (g/grid {}
+                   (g/row {:class "show-grid"}
+                          (g/col {:xs 12 :md 8}
+                                 (d/code {} "(g/col {:xs 12 :md 8})"))
+                          (g/col {:xs 6 :md 4}
+                                 (d/code {} "(g/col {:xs 6 :md 4})")))
+                   (g/row {:class "show-grid"}
+                          (g/col {:xs 6 :md 4}
+                                 (d/code {} "(g/col {:xs 6 :md 4})"))
+                          (g/col {:xs 6 :md 4}
+                                 (d/code {} "(g/col {:xs 6 :md 4})"))
+                          (g/col {:xs 6 :md 4}
+                                 (d/code {} "(g/col {:xs 6 :md 4})")))
+                   (g/row {:class "show-grid"}
+                          (g/col {:xs 6 :xs-offset 6}
+                                 (d/code {} "(g/col {:xs 6 :xs-offset 6})")))
+                   (g/row {:class "show-grid"}
+                          (g/col {:md 6 :md-push 6}
+                                 (d/code {} "(g/col {:md 6 :md-push 6})"))
+                          (g/col {:md 6 :md-pull 6}
+                                 (d/code {} "(g/col {:md 6 :md-push 6})"))))))
 
 ;; ## Tooltip
 
 (def tooltip-example
-  (d/div {:class "bs-example"}
-         (d/div {:style {:height 50}}
-                (r/tooltip {:placement "right"
-                            :position-left 150
-                            :position-top 50}
-                           (d/strong "Holy guacamole!")
-                           "Check this info."))))
+  (example {:style {:height 50}}
+           (r/tooltip {:placement "right"
+                       :position-left 150
+                       :position-top 50}
+                      (d/strong "Holy guacamole!")
+                      "Check this info.")))
 
 (comment
 

  []
  (render [_]
          (d/div
           (button-block)
           (d/h3 "Panels")
           (panel-example)
           (d/h3 "Jumbotron")
           (jumbotron-example)
           (d/h3 "Label Examples")
           (label-examples)
           (d/h3 "Label Variations")
           (label-variations)
           (d/h3 "Well!")
           default-well
           optional-well-classes
           (d/h3 "Page Header")
           header-example
           (d/h3 "Grid")
           grid-example
           (d/h3 "Tooltip")
           tooltip-example
           (d/h3 "Positioned Tooltip (in progress)")
           (d/h3 "Alert")
           alert-example
           (d/h3 "Popover")
           popover-example
           (d/h3 "Nav")
           nav-example
           (d/h3 "Badges")
           badge-example)))

(defonce app-state
  (atom {:text "Hi!"}))


(def alert-example
  "Basic alert styles:"
  (example
   (r/alert {:bs-style "warning"}
            (d/strong "Holy guacamole!")
            "Best check yo self, you're not looking too good.")))

(comment
  "TODO: Closeable alerts, just pass in a onDismiss function."
