(ns super-koalio.core
  (:require [play-clj.core :refer :all]
            [play-clj.g2d :refer :all]
            [play-clj.ui :refer :all]
            [super-koalio.entities :as e]
            [super-koalio.utils :as u]))

(declare super-koalio main-screen text-screen)

;; Called by screen's on-render
(defn update-screen!
  [screen entities]
  (doseq [{:keys [x y height me? to-destroy]} entities]
    ;; me? only true for player character
    (when me?
      ;; fix the camera position on the player
      (position! screen x (/ u/vertical-tiles 2))
      ;; if player has fallen in a pit
      (when (< y (- height))
        ;; How does this effect a restart?  does it trigger :on-show
        ;; again?  TODO Worth testing w/a debug line...
        (set-screen! super-koalio main-screen text-screen)))
    ;; This syntax doesn't make sense to me, you want a list with two
    ;; named variables when to-destroy is true... but how do tile-x
    ;; and tile-y get initialised to anything?  I guess there's an
    ;; implied entity in the when-let vector too but how can it know
    ;; to put its x and y in tile-x and tile-y?
    (when-let [[tile-x tile-y] to-destroy]
      ;; Null the block @ tile-x and tile-y (because it's been bonked)
      ;; (So if you want to put in items popping out or whatever you
      ;; could do it here... or are those new entities?)
      (tiled-map-layer! (tiled-map-layer screen "walls")
                        :set-cell tile-x tile-y nil)))
  ;; take off to-destroy entities
  (map #(dissoc % :to-destroy) entities))

(defscreen main-screen
  :on-show
  (fn [screen entities]
    (->> (orthogonal-tiled-map "level1.tmx" (/ 1 u/pixels-per-tile))
         (update! screen :timeline [] :camera (orthographic) :renderer))
    (let [sheet (texture "koalio.png")
          tiles (texture! sheet :split 18 26)
          player-images (for [col [0 1 2 3 4]]
                          (texture (aget tiles 0 col)))]
      ;; ?? create's arguments are [stand jump & walk], none of which
      ;; are properties of texture... AHA, no: it means col 0 is standing
      ;; texture, 1 is jumping texture, and 2-4 are walking textures :)
      (apply e/create player-images)))
  
  :on-render
  (fn [screen entities]
    ;; Blank screen to specified colour (r g b a)
    (clear! 0.5 0.5 1 1)
    (some->> (if (or (key-pressed? :space) (u/touched? :center))
               ;; if space then rewind 
               (rewind! screen 2)
               ;; else tell every entity to do its thing (move, then
               ;; prevent move, then animate (qv))
               (map (fn [entity]
                      (->> entity
                           (e/move screen)
                           (e/prevent-move screen)
                           (e/animate screen)))
                    entities))
             ;; As long as the if returned not-nil (what does it
             ;; return?), then render
             (render! screen)
             ;; As long as the if returned not-nil (what does it
             ;; return?), then update screen
             (update-screen! screen)))
  
  :on-resize
  (fn [{:keys [width height] :as screen} entities]
    ;; Sets the height of the camera in screen, adjusting the width so
    ;; the ratio remains in tact.
    (height! screen u/vertical-tiles)))

(defscreen text-screen
  :on-show
  (fn [screen entities]
    (update! screen :camera (orthographic) :renderer (stage))
    (assoc (label "0" (color :white))
           :id :fps
           :x 5))
  
  :on-render
  (fn [screen entities]
    (->> (for [entity entities]
           (case (:id entity)
             :fps (doto entity (label! :set-text (str (game :fps))))
             entity))
         (render! screen)))
  
  :on-resize
  (fn [screen entities]
    (height! screen 300)))

(defgame super-koalio
  :on-create
  (fn [this]
    (set-screen! this main-screen text-screen)))