(ns advent.actions
  (:require [play-clj.core :refer :all]
            [play-clj.ui :refer :all]
            [play-clj.utils :refer :all]
            [play-clj.g2d :refer :all]
            [clojure.pprint]
            [advent.pathfind]
            [advent.actions :as actions]
            [advent.screens.dialogue :as dialogue])
  (:import [com.badlogic.gdx.graphics Pixmap Pixmap$Filter Texture Texture$TextureFilter]
           [com.badlogic.gdx.graphics.g2d TextureRegion]))

(defn jump-to [screen entities entity [x y]]
  (let [scale-fn (-> entities :background :scale-fn)
        entity (assoc entity :x x
                      :y y
                      :baseline (- 240 y))]
    (if (:scaled entity)
      (assoc entity :scale-x (scale-fn y) :scale-y (scale-fn y))
      entity)))

(defn walk-to [[target-x target-y] target-id]
  (fn [screen entities]
    (let [{from-x :x from-y :y :keys [left right anim] :as target-entity} (entities target-id)]
      (let [delta-x (- target-x from-x)
            delta-y (- target-y from-y)
            mag (Math/sqrt (+ (* delta-x delta-x) (* delta-y delta-y)))
            moved-x (* 1.5 (/ delta-x mag))
            moved-y (* 1.5 (/ delta-y mag))]
        (if (< mag 1)
          (assoc entities target-id (assoc target-entity :actions (rest (:actions target-entity)) :anim nil))
          (assoc entities target-id
                 (assoc (jump-to screen entities target-entity [(+ moved-x from-x) (+ moved-y from-y)])
                   :anim (if (< moved-x 0) left right))))))))

(defn stop [target-id]
  (fn [screen entities]
    (let [target (target-id entities)]
      (run! dialogue/talking-screen :stop-talk :target-id target-id)
      (assoc-in entities [target-id] (merge target
                                            {:anim nil
                                             :actions (rest (:actions target))}
                                            (when (:anim target)
                                              (texture (animation! (:anim target) :get-key-frame 0.25))))))))

(defn from-path [screen entities target-id [x y]]
  (let [entity (target-id entities)
        path (vec (take-nth 2 (advent.pathfind/visit-all
                               (:collision (:background entities))
                               [(int (:x entity)) (int (:y entity))]
                               [(int x) (int y)])))
        actions (when (seq path)
                  (concat
                   [(stop target-id)]
                   (map #(walk-to % target-id) (conj path [x y]))
                   [(stop target-id)]))]
    actions))

(defn talk [target-id text]
  (fn [screen entities]
    (let [target-y (get-in entities [target-id :y])
          scale-fn (get-in entities [:background :scale-fn])
          scale (scale-fn target-y)
          height (* scale 36)]
      (run! dialogue/talking-screen :on-talk :text text 
            :x (get-in entities [target-id :x]) :y (+ (get-in entities [target-id :y]) height)
            :target-id target-id
            :scale scale)
      (-> entities 
          (update-in [target-id :actions] rest)
          (assoc-in [target-id :anim] (get-in entities [target-id :talk]))))))
