######################################################
(if (= (os/which) :windows)
  (if (os/stat "D:/Projects")
    (os/cd "D:/Projects/Myxle/janet")
    (os/cd "C:/bin/fossil/myxle/janet"))
  (os/cd "/home/mlatu/#work#/myxle/janet"))

(use "./modules/myxle")

#(once keyword quoted-fn)
#      for settings, asset loads etc. as name implies, is supposed
#      to be called once, result is saved in instructiontable inside
#      hotloop environment under the keyword

#(import ".\\modules\\ffi-raylib" :as rl-ffi)
# loads module and changes hotloop environment
# returns nil, nothing to lookup
(once :import-raylib
   '(fn []
     (import "./ffi-raylib" :as rl)
    nil))


#(rl-ffi/init-window
# 800 600
# "hello raylib, this is janet via ffi")
#
#> opens opengl window, returns nil

#(rl-ffi/set-target-fps
# 60)
#
#> sets framerate, returns nil

#> return window settings for later lookup under keyword :init-raylib
(once :init-raylib
'(fn init-raylib []
   (let [it (dyn :instructiontable)
         oi (get-in it [:once :init-raylib :result]
                        {:window {:size {:x 800 :y 600}
                                  :title "hello raylib, this is janet via ffi"
                                  :fps 60}})
        {:window {:size {:x x :y y}
                  :title title
                  :fps fps}} oi]
      (rl/init-window x y title)
      (rl/set-target-fps fps)
      oi)))

(do
  (once :rng
     '(fn seed-rng []
       (math/rng (os/time))))
  
  (system+ :screenpositionscrambler
     '(fn screenpositionscrambler [component]
       (when-let
	   [{:entity entity-id :system targetsystem} component
	    it (dyn :instructiontable)
	    {:x maxx :y maxy} (get-in it [:once :init-raylib :result :window :size])
	    apptime (get-in it [:time :app])
	    rng (get-in it [:once :rng :result])
	    offset (get-in it [:systems targetsystem
			       :components entity-id
			       :timingoffset])
	    newx (math/floor (+ 100 (* 0.4 maxx (math/sin (+ offset apptime)))))
	    newy (math/floor (* 0.2 maxy (math/cos (+ offset apptime))))
	    randomy (math/rng-int rng maxy)
	    randomx (math/rng-int rng maxx)]
	 (as-> it X
	       (put-in X [:systems targetsystem :components entity-id :position] @{:x newx :y newy})
	       (setdyn :instructiontable X))
	 )))
  
  #systems iterate over their components every frame
  # use lenna-texture array from once-call to display a sprite
  (system+ :sprite
     '(fn sprite [component]
       (when-let
	   [{:entity entity-id :texture texture :tint tint :position {:x x :y y}} component]
	 (rl/draw-texture texture x y tint)
	 )))
  
  (fnstack-clear :pre)
  (fnstack-clear :post)
  (fnstack-clear :exit)
  
  (fnstack-push :pre
     '(let [it                  (dyn :instructiontable)
	    ostime              (os/time)
	    default-time        {:os ostime :framecount 0}
	    {:os oldostime
	     :framecount oldfc} (get-in it [:time] default-time)
	    newframecount       (if (= oldostime ostime)
				  (inc oldfc)
				  oldfc)
	    frametime           (rl/get-frame-time)
	    apptime             (rl/get-time)]
       (setdyn :instructiontable
	  (put-in it
		  [:time]
		  {:frame frametime
		   :app apptime
		   :os ostime
		   :framecount newframecount}))))

  (fnstack-push :pre
     '(do
       (rl/begin-drawing)))

  (fnstack-push :pre
     '(do
       (rl/clear-background [0 0 0 0xff])))
  
  (fnstack-push :post
     '(do
       (rl/draw-fps 400 300)
       (rl/end-drawing)))
  
  (fnstack-push :exit
     '(do
       (pp "unloading texture")
       (rl-ffi/unload-texture lenna-t)))
  
  (fnstack-push :exit
     '(do
       (pp "closing window")
       (rl-ffi/close-window))))

(comment
 # tools:
 (exit)
 (inbox-size)
 
 (while (pos? ((inbox-size) :supervisor)) 
   (printf "there was an error: %q" (inbox-size))
   (pp (get-inbox)))
 
 (take-back-parameter)
 
 #(load-texture or similar lenna.jpg) -> array with texture id on gpu    
 (once :lenna
    '(fn load-lenna []
      (let [path-to-lenna (if (= (os/which) :windows)
			    "D:\\Projects\\lain\\janet\\jaylib\\test\\lenna.png"
			    "/home/mlatu/#work#/jaylib/test/lenna.png")
	    image (rl/load-image-1 path-to-lenna)
	    image-dithered (rl/image-dither image 4 4 4 4)]
	(rl/load-texture-from-image image-dithered))))
 
 
 (def og-lenna
   '(let [entity-id :lenna 
	    it (dyn :instructiontable)
	  once-upon-a-texture (get-in it [:once entity-id :result])
	  rng (get-in it [:once :rng :result])
	  offset (math/rng-int rng)]
     @{:texture (tuple/brackets ;once-upon-a-texture)
       :tint (array/new-filled 4 0xff)
       :position @{:x 0 :y 0}
       :timingoffset offset}))
 
 (def og-scrambler
   '@{:system :sprite})
 
 (component+ :lenna :sprite og-lenna)
 (component+ :lenna :screenpositionscrambler og-scrambler)
 
 (component+ :lenna-0 :sprite og-lenna)
 (component+ :lenna-0 :screenpositionscrambler og-scrambler)
 
 (map |(let [id (keyword (string/format "lenna-%q" $0))]
	 (component+ id :sprite og-lenna)
	 (component+ id :screenpositionscrambler og-scrambler)) 
      (range 100))
 
 (map |(let [id (keyword (string/format "lenna-%q" $0))]
	 (component- id :screenpositionscrambler)
	 (component- id :sprite)) (range 100))
 
 (component- :lenna :sprite)
 (component- :lenna :screenpositionscrambler)
 
 (component- :lenna-0 :sprite)
 (component- :lenna-0 :screenpositionscrambler)
) #comment for tools
