(ns sekai.core.testing
  (:require [sekai.core.entity :as e]
            [sekai.core.gamestate :as gs :refer [game-state]]
            [sekai.entity.selector :as s]
            [sekai.core.event :as event]
            [sekai.core.component :as comp]
            [sekai.core.logging :as logging :refer [log]]
            [clojure.test :as t
             :refer [use-fixtures
                     deftest
                     testing
                     run-tests
                     is]]
            [sekai.entity.selector :as selector]))

(use-fixtures :once
  (fn [tests]
    (let [orig-state (swap! game-state identity)]
      (log :info "Test Setup")
      (gs/reset-game-state! nil)

      (tests)

      (log :info "Test Teardown")
      (reset! game-state orig-state))))

(use-fixtures :each
  (fn [test]
    (gs/reset-game-state! nil)
    (test)))

(deftest register-entity!
  (testing "Entity Registration"
    (is (e/register-entity!))))

(deftest component-position
  (testing "Position Component"
    (let [eid (e/register-entity!)]
      (comp/attach! (comp/position 0 2 0) eid)
      (let [c (e/get-component eid :position)]
        (is (:x c) 0)
        (is (:y c) 2))
      (is (contains? (s/gather (s/with-tag :spatial)) eid))
      (comp/detach! :position eid)
      (is (not (contains? (s/gather (s/with-tag :spatial)) eid))))))

(deftest selector
  (testing "Selectors"
    (let [eid1 (e/register-entity!)
          eid2 (e/register-entity!)
          eid3 (e/register-entity!)]
      (e/register-tag! eid1 :one)
      (e/register-tag! eid1 :two)
      (e/register-tag! eid2 :one)
      (e/register-tag! eid2 :two)
      (e/register-tag! eid3 :threee)
      (let [all (s/gather (s/with-tags :one :two))
            some (s/gather (s/some-tags :one :three))]
        (is (contains? all eid1))
        (is (contains? all eid2))
        (is (not (contains? all eid3)))

        (is (every? #(contains? some %) [eid1 eid2 eid3]))))))
