 (defprotocol IDrawable
   (draw! [_ ctx]))
 
+(extend-type GameStartScreen
+  IDrawable
+  (draw! [_ ctx]
+    (.save ctx)
+    (aset ctx "textAlign" "center")
+    ;;
+    (aset ctx "font" "60px Helvetica")
+    (aset ctx "fillStyle" "peru")
+    (.fillText ctx "Welcome to Pong!" (/ SCALE-W 2) 100)
+    ;;
+    (aset ctx "font" "italic 14px Helvetica")
+    (aset ctx "fillStyle" "slategray")
+    (.fillText ctx "single player" (/ SCALE-W 2) 150)
+    ;;
+    (aset ctx "font" "20px Helvetica")
+    (aset ctx "fillStyle" "dodgerblue")
+    (.fillText ctx "Press the spacebar to start." (/ SCALE-W 2) 300)
+    ;;
+    (aset ctx "font" "italic 12px Helvetica")
+    (aset ctx "fillStyle" "slategray")
+    (.fillText ctx "[ Right ] and [ Left ] arrows to switch paddles." (/ SCALE-W 2) 370)
+    (.fillText ctx "[ Up ] and [ Down ] arrows to move paddles." (/ SCALE-W 2) 390)
+    (.fillText ctx "[ Spacebar ] to pause ." (/ SCALE-W 2) 410)
+    (.fillText ctx "[ Escape ] to quit." (/ SCALE-W 2) 430)
+    (.restore ctx)))
+
+(extend-type Line
+  IDrawable
+  (draw! [{:keys [x1 y1 x2 y2 color] :as line} ctx]
+    (.save ctx)
+    (aset ctx "lineWidth" "1")
+    (aset ctx "strokeStyle" color)
+    (.setLineDash ctx (array 1 2))
+    (.beginPath ctx)
+    (.moveTo ctx x1 y1)
+    (.lineTo ctx x2 y2)
+    (.stroke ctx)
+    (.closePath ctx)
+    (.restore ctx)))
+
 (extend-type Score
   IDrawable
-  (draw! [{:keys [score x y font color] :as Score} ctx]
+  (draw! [{:keys [score x y font color align]} ctx]
+    (.save ctx)
     (aset ctx "font" font)
     (aset ctx "fillStyle" color)
-    (aset ctx "textAlign" "center")
+    (aset ctx "textAlign" align)
     (.fillText ctx (str score) x y)
-    ctx))
+    (.restore ctx)))
 
 (extend-type Paddle
   IDrawable
-  (draw! [paddle ctx]
-    (let [{:keys [color x y width height]} paddle]
-      (aset ctx "fillStyle" color)
-      (.fillRect ctx x y width height))
-    ctx))
+  (draw! [{:keys [color x y width height]} ctx]
+    (.save ctx)
+    (aset ctx "fillStyle" color)
+    (.fillRect ctx x y width height)
+    (.restore ctx)))
 
 (extend-type Ball
   IDrawable
   (draw! [{:keys [x y radius fill-color] :as ball} ctx]
+    (.save ctx)
     (aset ctx "fillStyle" fill-color)
     (.beginPath ctx)
     (.arc ctx x y radius 0 (* 2 js/Math.PI) false)
     (.fill ctx)
     (.closePath ctx)
-    ctx))
+    (.restore ctx)))
 
 (extend-type Rect
   IDrawable
-  (draw! [rect ctx]
-    (let [{:keys [color x y width height]} rect]
-      (aset ctx "lineWidth" "0.5")
-      (aset ctx "fillStyle" color)
-      (aset ctx "strokeStyle" "black")
-      (.fillRect ctx x y width height)
-      (.strokeRect ctx x y width height))
-    ctx))
+  (draw! [{:keys [color x y width height]} ctx]
+    (.save ctx)
+    (aset ctx "lineWidth" "0.5")
+    (aset ctx "fillStyle" color)
+    (aset ctx "strokeStyle" "black")
+    (.fillRect ctx x y width height)
+    (.strokeRect ctx x y width height)
+    (.restore ctx)))
 
 (extend-type Frame
   IDrawable
-  (draw! [frame ctx]
-    (let [{:keys [color x y width height frame-width]} frame]
-      (aset ctx "lineWidth" (str frame-width))
-      (aset ctx "strokeStyle" color)
-      (.strokeRect ctx x y width height))
-    ctx))
+  (draw! [{:keys [color x y width height frame-width]} ctx]
+    (.save ctx)
+    (aset ctx "lineWidth" (str frame-width))
+    (aset ctx "strokeStyle" color)
+    (.strokeRect ctx x y width height)
+    (.restore ctx)))
 
 ;;-----------------------------------------------------------------------------
 ;; Moveable Objects

    (when-let [event (<! ch)]
      (cond
        (contains? #{:up :down} event)
        (swap! state (fn [{id :current-paddle :as state}]
                       (assoc state id (control! (id state) event))))

        (contains? #{:paddle-1 :paddle-2} event)
        (swap! state assoc :current-paddle event)

        :else
        (println "Unhandled event:" event))


(defn animate-loop!
  [state ctx]
  (when-not (:pause? @state)
    (when (= (:mode @state) :playing)
      (swap! state #(-> % move-phase! collision-phase! score-phase!)))
    (draw-phase! state ctx))
  (.requestAnimationFrame js/window (partial animate-loop! state ctx)))

;;-----------------------------------------------------------------------------
