 
           (let [direction (msg :direction)
                 update-entity-args (case (msg :type)
-                                     :move-key-down [[:input :intended-move-direction] conj direction]
-                                     :move-key-up [[:input :intended-move-direction] disj direction]
-                                     :fire-key-down [[:input :intended-fire-direction]
+                                     :move-key-down [[:component/input :input/intended-move-direction] conj direction]
+                                     :move-key-up [[:component/input :input/intended-move-direction] disj direction]
+                                     :fire-key-down [[:component/input :input/intended-fire-direction]
                                                      (fn [fire-directions]
                                                        (if (in? fire-directions direction)
                                                          fire-directions
                                                          (conj fire-directions direction)))]
-                                     :fire-key-up [[:input :intended-fire-direction]
+                                     :fire-key-up [[:component/input :input/intended-fire-direction]
                                                    (fn [fire-directions]
                                                      (filterv #(not= direction %) fire-directions))])]
 

                               :left  Math/PI
                               :right 0})

(sm/defn remove-conflicting-directions :- [IntendedDirection]
  "Takes a seq of directions like #{:up :down :left} and returns a seq of directions
  where the pairs of conflicting directions - up+down, left+right - are stripped out if they're present."
  [directions :- [IntendedDirection]]
  (reduce (fn [directions conflicting-pair]
            (if (= (intersection directions conflicting-pair)
                   conflicting-pair)

          directions
          [#{:up :down} #{:left :right}]))

(s/fdef remove-conflicting-directions
  :args (s/cat :directions (s/coll-of :input/intended-direction))
  :ret (s/coll-of :input/intended-direction)
  :fn #(subset? (-> % :args :directions)
                (% :ret)))

(defn human-controlled-entity-movement-directions
  [entity]
  (-> entity
      (safe-get-in [:component/input :input/intended-move-direction])
      remove-conflicting-directions))

(s/fdef human-controlled-entity-movement-directions
  :args (s/and (s/cat :entity :entity/entity)
               #(contains? (% :entity) :component/input))
  :ret (s/coll-of :input/intended-direction))

(defn intended-directions->angle
  [intended-directions]
  (let [intended-direction-values (map direction-value-mappings intended-directions)]
    (Math/atan2 (apply + (map Math/sin intended-direction-values))
                (apply + (map Math/cos intended-direction-values)))))

(s/fdef intended-directions->angle
  :args (s/cat :intended-directions (s/coll-of :input/intended-direction))
  :ret :geometry/direction)

(defn update-move-direction
  [entity]
  (let [intended-directions (human-controlled-entity-movement-directions entity)]
    (if (seq intended-directions)
      (assoc-in entity
                [:component/motion :motion/direction]
                (intended-directions->angle intended-directions))
      ; xxxx TODO come back and make sure i understand the semantics of :motion :direction being nil
      (assoc-in entity
                [:component/motion :motion/direction]
                nil))))

(s/fdef update-move-direction
  :args (s/and (s/cat :entity :entity/entity)
               #(contains? (% :entity) :component/input))
  :ret :entity/entity)

(defn update-fire-direction
  [entity]
  (let [intended-direction (last (get-in entity [:component/input :input/intended-fire-direction]))]
    (if intended-direction
      (assoc-in entity
                [:component/weapon :weapon/fire-direction]
                (intended-directions->angle [intended-direction]))
      (assoc-in entity [:component/weapon :weapon/fire-direction] nil))))

(s/fdef update-fire-direction
  :args (s/and (s/cat :entity :entity/entity)
               #(contains? (% :entity) :component/input))
  :ret :entity/entity)

;;; Public

