;;-*-Lisp-*-
(in-package goal)

;; failed to figure out what this is:
(defstate cam-combiner-active (camera-combiner)
  :event (behavior ((arg0 process) (arg1 int) (arg2 symbol) (arg3 event-message-block))
    (let ((v1-0 arg2))
      (the-as
        object
        (cond
          ((= v1-0 'point-of-interest)
           (cond
             ((-> arg3 param 0)
              (set! (-> self tracking use-point-of-interest) #t)
              (set! (-> self tracking point-of-interest quad) (-> (the-as vector (-> arg3 param 0)) quad))
              (let ((f0-0 1.0))
                (set! (-> self tracking point-of-interest-blend target) f0-0)
                f0-0
                )
              )
             (else
               (set! (-> self tracking use-point-of-interest) #f)
               (let ((f0-1 0.0))
                 (set! (-> self tracking point-of-interest-blend target) f0-1)
                 f0-1
                 )
               )
             )
           )
          ((= v1-0 'set-interpolation)
           (set! (-> self interp-val) 0.0)
           (let ((f0-4 (/ 5.0 (the float (-> arg3 param 0)))))
             (set! (-> self interp-step) f0-4)
             f0-4
             )
           )
          ((= v1-0 'teleport)
           (when (nonzero? (-> self tracking-status))
             (cam-calc-follow! (-> self tracking) (-> self trans) #f)
             (slave-set-rotation!
               (-> self tracking)
               (-> self trans)
               (the-as float (-> self tracking-options))
               (-> self fov)
               #f
               )
             )
           )
          ((= v1-0 'stop-tracking)
           (set! (-> self tracking-status) (the-as uint 0))
           0
           )
          ((= v1-0 'start-tracking)
           (cond
             ((< arg1 1)
              (let ((t9-2 format)
                    (a0-15 0)
                    (a1-3 "ERROR <GMJ>: missing camera-slave parameter to *camera-combiner* start-tracking~%")
                    )
                (let ((v1-7 (-> arg3 param 0)))
                  (rtype-of v1-7)
                  )
                (t9-2 a0-15 a1-3)
                )
              )
             ((let ((t9-3 type-type?)
                    (v1-8 (-> arg3 param 0))
                    )
                (not (t9-3 (rtype-of v1-8) camera-slave))
                )
              (let ((t9-4 format)
                    (a0-18 0)
                    (a1-5 "ERROR <GMJ>: invalid type '~A' to *camera-combiner* start-tracking~%")
                    (v1-10 (-> arg3 param 0))
                    )
                (t9-4 a0-18 a1-5 (rtype-of v1-10))
                )
              )
             ((zero? (-> self tracking-status))
              (set! (-> self tracking-status) (the-as uint 1))
              (let ((gp-1 (the-as object (-> arg3 param 0))))
                (set! (-> self tracking-options) (the-as int (-> (the-as camera-slave gp-1) options)))
                (set! (-> self tracking no-follow) (-> (the-as camera-slave gp-1) tracking no-follow))
                (copy-cam-float-seeker (-> self tracking tilt-adjust) (-> (the-as camera-slave gp-1) tracking tilt-adjust))
                (copy-cam-float-seeker
                  (-> self tracking underwater-blend)
                  (-> (the-as camera-slave gp-1) tracking underwater-blend)
                  )
                (set! (-> self tracking use-point-of-interest) (-> (the-as camera-slave gp-1) tracking use-point-of-interest))
                (set! (-> self tracking point-of-interest quad)
                      (-> (the-as camera-slave gp-1) tracking point-of-interest quad)
                      )
                (copy-cam-float-seeker
                  (-> self tracking point-of-interest-blend)
                  (-> (the-as camera-slave gp-1) tracking point-of-interest-blend)
                  )
                (let ((gp-2 (+ (the-as uint gp-1) 108)))
                  (cam-calc-follow! (-> self tracking) (the-as vector gp-2) #f)
                  (slave-set-rotation!
                    (-> self tracking)
                    (the-as vector gp-2)
                    (the-as float (-> self tracking-options))
                    (-> self fov)
                    #f
                    )
                  )
                )
              )
             )
           )
          ((= v1-0 'copy-tracking)
           (cond
             ((< arg1 1)
              (let ((t9-10 format)
                    (a0-27 0)
                    (a1-11 "ERROR <GMJ>: missing camera-slave parameter to *camera-combiner* copy-tracking~%")
                    )
                (let ((v1-23 (-> arg3 param 0)))
                  (rtype-of v1-23)
                  )
                (t9-10 a0-27 a1-11)
                )
              )
             ((let ((t9-11 type-type?)
                    (v1-24 (-> arg3 param 0))
                    )
                (not (t9-11 (rtype-of v1-24) camera-slave))
                )
              (let ((t9-12 format)
                    (a0-30 0)
                    (a1-13 "ERROR <GMJ>: invalid type '~A' to *camera-combiner* copy-tracking~%")
                    (v1-25 (-> arg3 param 0))
                    )
                (t9-12 a0-30 a1-13 (rtype-of v1-25))
                )
              )
             ((nonzero? (-> self tracking-status))
              #f
              )
             (else
               (set! (-> self tracking-status) (the-as uint 1))
               (let ((gp-3 (the-as camera-slave (-> arg3 param 0))))
                 (set! (-> self tracking-options) (the-as int (-> gp-3 options)))
                 (set! (-> self tracking no-follow) (-> gp-3 tracking no-follow))
                 (copy-cam-float-seeker (-> self tracking tilt-adjust) (-> gp-3 tracking tilt-adjust))
                 (copy-cam-float-seeker (-> self tracking underwater-blend) (-> gp-3 tracking underwater-blend))
                 (set! (-> self tracking follow-off quad) (-> gp-3 tracking follow-off quad))
                 (set! (-> self tracking follow-pt quad) (-> gp-3 tracking follow-pt quad))
                 (let* ((a2-17 (-> self tracking))
                        (a3-3 (-> gp-3 tracking))
                        (v1-36 (-> a3-3 inv-mat vector 0 quad))
                        (a0-37 (-> a3-3 inv-mat vector 1 quad))
                        (a1-16 (-> a3-3 inv-mat vector 2 quad))
                        (a3-4 (-> a3-3 inv-mat vector 3 quad))
                        )
                   (set! (-> a2-17 inv-mat vector 0 quad) v1-36)
                   (set! (-> a2-17 inv-mat vector 1 quad) a0-37)
                   (set! (-> a2-17 inv-mat vector 2 quad) a1-16)
                   (set! (-> a2-17 inv-mat vector 3 quad) a3-4)
                   )
                 (set! (-> self tracking use-point-of-interest) (-> gp-3 tracking use-point-of-interest))
                 (set! (-> self tracking point-of-interest quad) (-> gp-3 tracking point-of-interest quad))
                 (copy-cam-float-seeker (-> self tracking point-of-interest-blend) (-> gp-3 tracking point-of-interest-blend))
                 )
               )
             )
           )
          )
        )
      )
    )
  :code (behavior ()
    (local-vars (sv-160 cam-rotation-tracker))
    (loop
      (when (and (zero? (logand (-> *camera* master-options) 2)) (!= (-> self tracking-status) 0))
        (set! (-> self tracking-status) (the-as uint 0))
        0
        )
      (when *camera*
        (let ((s5-0 (-> *camera* slave 0))
              (s4-0 (-> *camera* slave 1))
              (f30-0 (parameter-ease-sin-clamp (-> self interp-val)))
              (gp-0 (new-stack-vector0))
              )
          (set! (-> gp-0 quad) (-> self trans quad))
          (when s5-0
            (cond
              (s4-0
                (vector-lerp-clamp! (-> self trans) (-> s5-0 0 trans) (-> s4-0 0 trans) f30-0)
                (set! (-> self fov) (lerp-clamp (-> s5-0 0 fov) (-> s4-0 0 fov) f30-0))
                (set! (-> self dist-from-src) (vector-vector-distance (-> self trans) (-> s5-0 0 trans)))
                (set! (-> self dist-from-dest) (vector-vector-distance (-> self trans) (-> s4-0 0 trans)))
                (cond
                  ((= (-> self tracking-status) 1)
                   (cam-calc-follow! (-> self tracking) (-> self trans) #t)
                   (slave-set-rotation!
                     (-> self tracking)
                     (-> self trans)
                     (the-as float (-> self tracking-options))
                     (-> self fov)
                     #t
                     )
                   (let* ((a2-4 (-> self inv-camera-rot))
                          (a3-2 (-> self tracking))
                          (v1-20 (-> a3-2 inv-mat vector 0 quad))
                          (a0-10 (-> a3-2 inv-mat vector 1 quad))
                          (a1-6 (-> a3-2 inv-mat vector 2 quad))
                          (a3-3 (-> a3-2 inv-mat vector 3 quad))
                          )
                     (set! (-> a2-4 vector 0 quad) v1-20)
                     (set! (-> a2-4 vector 1 quad) a0-10)
                     (set! (-> a2-4 vector 2 quad) a1-6)
                     (set! (-> a2-4 vector 3 quad) a3-3)
                     )
                   )
                  (else
                    (set! sv-160 (-> s5-0 0 tracking))
                    (let ((s2-0 (-> s5-0 0 trans))
                          (s5-1 (-> s4-0 0 tracking))
                          (s0-0 (-> s4-0 0 trans))
                          )
                      (cond
                        ((= (-> self tracking-status) 3)
                         (cam-calc-follow! (-> self tracking) s2-0 #t)
                         (slave-set-rotation! (-> self tracking) s2-0 (the-as float (-> self tracking-options)) (-> self fov) #t)
                         (set! sv-160 (-> self tracking))
                         (set! s2-0 (-> self trans))
                         )
                        ((= (-> self tracking-status) 2)
                         (cam-calc-follow! (-> self tracking) s0-0 #t)
                         (slave-set-rotation! (-> self tracking) s0-0 (the-as float (-> self tracking-options)) (-> self fov) #t)
                         (set! s5-1 (-> self tracking))
                         (set! s0-0 (-> self trans))
                         )
                        )
                      (let ((s1-0 (new 'stack-no-clear 'matrix)))
                        (dotimes (v1-35 3)
                          (set! (-> s1-0 vector v1-35 quad) (the-as uint128 0))
                          )
                        0.0
                        0.0
                        0.0
                        (let ((s4-1 (new-stack-vector0)))
                          0.0
                          (let ((s3-0 (new-stack-matrix0)))
                            (vector-!
                              (the-as vector (-> s1-0 vector))
                              (the-as vector (-> sv-160 inv-mat))
                              (the-as vector (-> s5-1 inv-mat))
                              )
                            (vector-! (-> s1-0 vector 1) (-> sv-160 inv-mat vector 1) (-> s5-1 inv-mat vector 1))
                            (vector-! (-> s1-0 vector 2) (-> sv-160 inv-mat vector 2) (-> s5-1 inv-mat vector 2))
                            (let ((f26-0 (vector-length (the-as vector (-> s1-0 vector))))
                                  (f28-0 (vector-length (-> s1-0 vector 1)))
                                  (f0-13 (vector-length (-> s1-0 vector 2)))
                                  )
                              (cond
                                ((and (< f26-0 f28-0) (< f26-0 f0-13))
                                 (vector-cross! s4-1 (-> s1-0 vector 1) (-> s1-0 vector 2))
                                 )
                                ((and (< f28-0 f26-0) (< f28-0 f0-13))
                                 (vector-cross! s4-1 (the-as vector (-> s1-0 vector)) (-> s1-0 vector 2))
                                 )
                                (else
                                  (vector-cross! s4-1 (the-as vector (-> s1-0 vector)) (-> s1-0 vector 1))
                                  )
                                )
                              )
                            (vector-normalize! s4-1 1.0)
                            (let ((f0-16 (fabs (vector-dot (the-as vector (-> sv-160 inv-mat)) s4-1)))
                                  (f1-2 (fabs (vector-dot (-> sv-160 inv-mat vector 1) s4-1)))
                                  (f2-2 (fabs (vector-dot (-> sv-160 inv-mat vector 2) s4-1)))
                                  )
                              (cond
                                ((and (< f0-16 f1-2) (< f0-16 f2-2))
                                 (vector-flatten! (the-as vector (-> s1-0 vector)) (the-as vector (-> sv-160 inv-mat)) s4-1)
                                 (vector-flatten! (-> s1-0 vector 1) (the-as vector (-> s5-1 inv-mat)) s4-1)
                                 )
                                ((< f1-2 f2-2)
                                 (vector-flatten! (the-as vector (-> s1-0 vector)) (-> sv-160 inv-mat vector 1) s4-1)
                                 (vector-flatten! (-> s1-0 vector 1) (-> s5-1 inv-mat vector 1) s4-1)
                                 )
                                (else
                                  (vector-flatten! (the-as vector (-> s1-0 vector)) (-> sv-160 inv-mat vector 2) s4-1)
                                  (vector-flatten! (-> s1-0 vector 1) (-> s5-1 inv-mat vector 2) s4-1)
                                  )
                                )
                              )
                            (vector-normalize! (the-as vector (-> s1-0 vector)) 1.0)
                            (vector-normalize! (-> s1-0 vector 1) 1.0)
                            (vector-cross! (-> s1-0 vector 2) (the-as vector (-> s1-0 vector)) (-> s1-0 vector 1))
                            (if (< (vector-dot (-> s1-0 vector 2) s4-1) 0.0)
                                (vector-negate! s4-1 s4-1)
                                )
                            (let ((f28-1 (acos (vector-dot (the-as vector (-> s1-0 vector)) (-> s1-0 vector 1)))))
                              (cond
                                ((logtest? (-> *camera* master-options) 8)
                                 (set! (-> *camera* master-options) (logand -25 (-> *camera* master-options)))
                                 (when (and (< 8192.0 f28-1) (logtest? (-> *camera* master-options) 2))
                                   (vector-! (the-as vector (-> s1-0 vector)) (-> *camera* tpos-curr) s2-0)
                                   (vector-! (-> s1-0 vector 1) s0-0 s2-0)
                                   (vector-flatten! (the-as vector (-> s1-0 vector)) (the-as vector (-> s1-0 vector)) (-> *camera* local-down))
                                   (vector-flatten! (-> s1-0 vector 1) (-> s1-0 vector 1) (-> *camera* local-down))
                                   (when (and (< 4096.0 (vector-normalize-ret-len! (the-as vector (-> s1-0 vector)) 1.0))
                                              (< 4096.0 (vector-normalize-ret-len! (-> s1-0 vector 1) 1.0))
                                              )
                                     (vector-cross! (-> s1-0 vector 2) (-> s1-0 vector 1) (the-as vector (-> s1-0 vector)))
                                     (when (< (vector-dot (-> s1-0 vector 2) s4-1) -0.01)
                                       )
                                     )
                                   )
                                 )
                                ((and (< 16384.0 f28-1) (< (vector-dot (-> self flip-control-axis) s4-1) 0.0))
                                 (logxor! (-> *camera* master-options) 16)
                                 )
                                )
                              (set! (-> self flip-control-axis quad) (-> s4-1 quad))
                              (when (logtest? (-> *camera* master-options) 16)
                                (set! f28-1 (- 65536.0 f28-1))
                                (vector-negate! s4-1 s4-1)
                                )
                              (let ((f30-1 (* f28-1 (- 1.0 f30-0))))
                                (matrix-axis-sin-cos! s3-0 s4-1 (sin f30-1) (cos f30-1))
                                )
                              )
                            (matrix*! (-> self inv-camera-rot) (the-as matrix s5-1) s3-0)
                            )
                          )
                        )
                      )
                    )
                  )
                (cond
                  ((and (< 0.0 (-> *camera* outro-t-step)) (< (-> *camera* outro-t) (-> *camera* outro-exit-value)))
                   )
                  ((and (< (-> *camera* outro-t-step) 0.0) (< (-> *camera* outro-exit-value) (-> *camera* outro-t)))
                   )
                  ((paused?)
                   )
                  (else
                    (+! (-> self interp-val) (* (-> self interp-step) (-> *display* time-adjust-ratio)))
                    )
                  )
                (when (>= (-> self interp-val) 1.0)
                  (deactivate (-> *camera* slave 0 0))
                  (set! (-> *camera* slave 0) (-> *camera* slave 1))
                  (set! (-> *camera* slave 1) (the-as (pointer camera-slave) #f))
                  (+! (-> *camera* num-slaves) -1)
                  )
                )
              (else
                (set! (-> self dist-from-src) 409600.0)
                (set! (-> self dist-from-dest) 0.0)
                (set! (-> self trans quad) (-> s5-0 0 trans quad))
                (set! (-> self fov) (-> s5-0 0 fov))
                (cond
                  ((= (-> self tracking-status) 2)
                   (set! (-> self tracking-status) (the-as uint 1))
                   )
                  ((= (-> self tracking-status) 3)
                   (set! (-> self tracking-status) (the-as uint 0))
                   0
                   )
                  )
                (cond
                  ((= (-> self tracking-status) 1)
                   (cam-calc-follow! (-> self tracking) (-> self trans) #t)
                   (slave-set-rotation!
                     (-> self tracking)
                     (-> self trans)
                     (the-as float (-> self tracking-options))
                     (-> self fov)
                     #t
                     )
                   (let* ((v1-143 (-> self inv-camera-rot))
                          (a3-8 (-> self tracking))
                          (a0-80 (-> a3-8 inv-mat vector 0 quad))
                          (a1-45 (-> a3-8 inv-mat vector 1 quad))
                          (a2-21 (-> a3-8 inv-mat vector 2 quad))
                          (a3-9 (-> a3-8 inv-mat vector 3 quad))
                          )
                     (set! (-> v1-143 vector 0 quad) a0-80)
                     (set! (-> v1-143 vector 1 quad) a1-45)
                     (set! (-> v1-143 vector 2 quad) a2-21)
                     (set! (-> v1-143 vector 3 quad) a3-9)
                     )
                   )
                  (else
                    (let* ((v1-144 (-> self inv-camera-rot))
                           (a3-10 (-> s5-0 0 tracking))
                           (a0-82 (-> a3-10 inv-mat vector 0 quad))
                           (a1-46 (-> a3-10 inv-mat vector 1 quad))
                           (a2-22 (-> a3-10 inv-mat vector 2 quad))
                           (a3-11 (-> a3-10 inv-mat vector 3 quad))
                           )
                      (set! (-> v1-144 vector 0 quad) a0-82)
                      (set! (-> v1-144 vector 1 quad) a1-46)
                      (set! (-> v1-144 vector 2 quad) a2-22)
                      (set! (-> v1-144 vector 3 quad) a3-11)
                      )
                    )
                  )
                )
              )
            )
          (vector-! (-> self velocity) (-> self trans) gp-0)
          )
        )
      (if (and *dproc* *debug-segment*)
          (add-frame
            (-> *display* frames (-> *display* on-screen) frame profile-bar 0)
            'camera
            (new 'static 'rgba :b #xff :a #x80)
            )
          )
      (suspend)
      )
    (none)
    )
  )

;; definition for function cam-combiner-init
;; INFO: Return type mismatch int vs none.
(defbehavior cam-combiner-init camera-combiner ()
  (stack-size-set! (-> self main-thread) 512)
  (set! *camera-combiner* self)
  (vector-reset! (-> self trans))
  (matrix-identity! (-> self inv-camera-rot))
  (if *math-camera*
      (set! (-> self fov) (-> *math-camera* fov))
      (set! (-> self fov) 11650.845)
      )
  (set! (-> self interp-val) 0.0)
  (set! (-> self interp-step) 0.125)
  (set! (-> self tracking-status) (the-as uint 0))
  (vector-reset! (-> self velocity))
  (go cam-combiner-active)
  0
  (none)
  )
