 (def ^:const snes-vendor-id  0x12bd)
 (def ^:const snes-product-id 0xd015)
 
+(def ^:private snes-axes
+  {:x-axis 0.0
+   :y-axis 0.0})
+
+(def ^:private snes-buttons
+  #{:X :A :B :Y :L :R :select :start})
 
 (def ^:private snes-bits
   {:X      [3 0]

    (log/warn
      (str "Incomplete data read from SNES controller: "
           (apply str (map (partial format "%02X") (take len buffer)))))
    (assoc
      (read-buttons snes-bits buffer)
      :x-axis (byte-axis (aget buffer 0))

    (into {})))


(defn- button-state-events
  "Calculates button press and release events. Returns a sequence of button
  press and release events."
  [buttons old-state new-state]
  (for [button buttons]
    (let [old-val (get old-state button)
          new-val (get new-state button)]
      (when (not= old-val new-val)
        {:type (if new-val :button/press :button/release)
         :source :gamepad
         :button button}))))


(defn- button-hold-events
  "Calculates repeated button hold events. Returns a sequence of events with
  the button and the elapsed ms it has been pressed for."
  [buttons state elapsed]
  (for [button buttons]
    (if (get state button)
      {:type :button/hold
       :source :gamepad
       :button button
       :elapsed elapsed})))


(defn- axis-direction-events
  "Calculates repeated axis direction events. Returns a sequence of events with
  the axis, the current value in [-1.0, 1.0], and the elapsed ms it has had
  that value."
  [axes state elapsed]
  (for [[axis default] axes]
    (let [value (get state axis)]
      (when (not= default value)
        {:type :axis/direction
         :source :gamepad
         :axis axis
         :value value
         :elapsed elapsed}))))

