 (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]

    (into {})))


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


(defn- repeat-events
  "Calculates repeated button 'hold' events, where the value differs from some
  default value. Sends an event with the button and the elapsed ms it has been
  pressed for."
  [buttons state elapsed]
  (for [[button default] buttons]
    (let [value (get state button)]
      (when (and (some? value) (not= value default))
        {:type :button/repeat
         :source :gamepad
         :button button
         :value value
         :elapsed elapsed}))))


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