(ns sekai.entity.entity
  (:require [sekai.core.gamestate
             :as gs
             :refer [game-state]]
            [sekai.core.logging :as logging :refer [log]]))

(defn set-component! [entity name data]
  (swap! game-state update-in [:entities entity]
         assoc name data))

(defn get-component [entity component-name]
  (get-in @game-state [:entities entity component-name]))

(defn register-component! [entity name data]
  (if-not (get-component entity name)
    (set-component! entity name data)
    (throw (ex-info "Component Doubly Registered"
                    {:entity entity :name name :data data}))))

(defn deregister-component! [entity component]
  (swap! game-state update-in [:entities entity] dissoc component))

(defn update-component! [entity component update-fn]
  (swap!
   game-state
   (fn [gs]
     (if-let [data (get-in @game-state [:entities entity component])]
       (do
         (log :info (str "update-component: " entity component (update-fn data)))
         (assoc-in gs [:entities entity component] (update-fn data)))
       (do (log :critical
            (str "Unknown Component " component
                 " for entity " entity))
           gs)))))

(defn register-entity! [& [name]]
  (let [eid (gensym (or name "entity_"))]
    (swap! game-state update-in [:entities] assoc eid {})
    (register-component! eid :tags #{})
    eid))

