 (ns slide-explorer.core
-  (:import (java.awt AlphaComposite BasicStroke Color Font Graphics Graphics2D
-                     Polygon RenderingHints)
+  (:import (java.awt AlphaComposite BasicStroke Color Font Graphics Graphics2D Image
+                     Polygon RenderingHints Shape)
            (java.awt.font TextAttribute)
+           (java.awt.geom Arc2D Arc2D$Double Ellipse2D$Double
+                          Line2D$Double Path2D$Double
+                          Rectangle2D$Double
+                          RoundRectangle2D$Double)
            (javax.swing JFrame JPanel)))
 
 ;; possible 

   [:round-rect
    {:l 20 :t 10 :w 300 :h 300
     :arc-radius 100
     :filled true :color :pink
     :rotate 50}]
   [:round-rect
    {:l 20 :t 10 :w 300 :h 300
     :arc-radius 100 :rotate 50
     :filled false :color 0xE06060
     :stroke {:width 5
              :cap :round
              :dashes [10 10] :dash-phase 0}}]
   [:ellipse
    {:l 25 :t 15 :w 110 :h 90
     :filled true :color :yellow :alpha 0.5}]
   [:polygon
    {:vertices [{:x 100 :y 100}
                {:x 50 :y 150}
                {:x 50 :y 220}
                {:x 160 :y 250}]
     :filled false
     :closed false
     :color :orange
     :alpha 0.8
     :stroke {:width 25
              :dashes [20 3 10 3 5 3]
              :cap :butt
              :join :bevel

        y (or y (+? t (half? h)))]
    (merge the-map {:w w :h h :l l :t t :r r :b b :x x :y y})))
   
(defmulti make-obj (fn [obj-keyword params] obj-keyword))

(defmethod make-obj :arc
  [_ {:keys [l t w h start-angle arc-angle arc-boundary closed]}]
  (let [type (condp = (or arc-boundary closed)
                             true Arc2D/PIE
                             :pie Arc2D/PIE
                             :chord Arc2D/CHORD
                             :open Arc2D/OPEN
                             Arc2D/OPEN)]
      (Arc2D$Double. l t w h start-angle arc-angle type)))

(defmethod make-obj :ellipse
  [_ {:keys [l t w h]}]
  (Ellipse2D$Double. l t w h))

(defmethod make-obj :rect
  [_ {:keys [l t w h]}]
  (Rectangle2D$Double. l t w h))

(defmethod make-obj :round-rect
  [_ {:keys [l t w h arc-radius arc-width arc-height]}]
  (RoundRectangle2D$Double. l t w h
                              (or arc-radius arc-width)
                              (or arc-radius arc-height)))

(defmethod make-obj :line
  [_ {:keys [l t r b]}]
  (Line2D$Double. l t r b))

(defmethod make-obj :polygon
  [_ {:keys [vertices]}]
  (let [xs (int-array (map :x vertices))
        ys (int-array (map :y vertices))
        n (count vertices)]
    (Polygon. xs ys n)))

(defmethod make-obj :polyline
  [_ {:keys [vertices]}]
  (let [path (Path2D$Double.)]
    (let [{:keys [x y]} (first vertices)]
      (.moveTo path x y))
    (doseq [{:keys [x y]} (rest vertices)]
      (.lineTo path x y))
    path))

(defmethod make-obj :text
  [_ {:keys [text]}]
  text)

(defmethod make-obj :image
  [_ {:keys [data]}]
  data)

(defn stroke? [stroke]
  (and stroke (pos? (:width stroke))))

(defmulti draw-primitive (fn [g2d obj params] (type obj)))

(defmethod draw-primitive Shape
  [g2d shape {:keys [fill stroke]}]
  (when fill
    (.fill g2d shape))
  (when (stroke? stroke)
    (.draw g2d shape)))

(defmethod draw-primitive Image
  [g2d image {:keys [l t w h]}]
  (.drawImage g2d image
              l t
              (or w (.getWidth image))
              (or h (.getHeight image)) nil))

(defn draw-string-center
  "Draw a string centered at position x,y."
