;; ---------------------------------------------------------------------------
;; L4: Render Loop
;; ---------------------------------------------------------------------------
(defcomp ()
  (~docs/page :title "Layer 4: Continuous Rendering Loop"

    (p (~tw :tokens "text-stone-500 text-sm italic mb-8")
      (code "requestAnimationFrame") " integration for canvas and animation apps, "
      "with automatic island lifecycle cleanup.")

    (~docs/section :title "Live Demo" :id "demo"
      (p "A ball bouncing across a track. Position is a signal — the " (code ":style") " attribute reads it reactively. The animation runs via " (code "set-interval") " at ~60fps; the effect's cleanup stops it when paused.")
      (~reactive-runtime/demo-loop)
      (~docs/code :src (highlight "(defisland ~demo-loop ()\n  (let ((running (signal true))\n        (x (signal 0))\n        (dir (signal 1))\n        (frames (signal 0)))\n    ;; Animation effect — interval simulates rAF\n    (effect (fn ()\n      (when (deref running)\n        (let ((id (set-interval\n            (fn ()\n              (batch (fn ()\n                (swap! frames inc)\n                (when (>= (deref x) 230) (reset! dir -1))\n                (when (<= (deref x) 0) (reset! dir 1))\n                (swap! x (fn (v) (+ v (* (deref dir) 3)))))))\n            16)))\n          (fn () (clear-interval id))))))\n    ;; Ball position driven by reactive style\n    (div :class \"relative h-12 ...\" :style (str \"...\")\n      (div :style (str \"left:\" (deref x) \"px\") ...))))" "lisp"))
      (p "The " (code "running") " signal is read in the effect body — toggling it triggers cleanup (stops the interval) and re-evaluation (starts a new one or does nothing). The real " (code "make-loop") " uses " (code "request-animation-frame") " with the running-ref pattern instead."))

    (~docs/section :title "API" :id "loop-api"

      (~docs/code :src (highlight
        "(define render-loop (make-loop (fn (timestamp dt)\n  (let ((ctx (ref-deref ctx-ref)))\n    (clear-canvas! ctx)\n    (draw-scene! ctx (deref elements))))))\n\n(loop-start! render-loop)\n(loop-stop! render-loop)\n(deref (loop-running? render-loop))  ;; => true (reactive)"
        "lisp")))

    (~docs/section :title "Running-Ref Pattern" :id "loop-pattern"

      (~docs/code :src (highlight
        ";; Internal: no cancelAnimationFrame needed\n(let ((running (ref true))\n      (last-ts (ref 0)))\n  (define tick (fn (ts)\n    (when (ref-deref running)\n      (let ((dt (- ts (ref-deref last-ts))))\n        (ref-set! last-ts ts)\n        (user-fn ts dt))\n      (request-animation-frame tick))))\n  (request-animation-frame tick)\n  ;; To stop: (ref-set! running false)\n  ;; Loop dies naturally on next frame check"
        "lisp"))

      (p "The loop checks a ref each frame. Setting it to " (code "false") " stops the loop "
         "without needing " (code "cancelAnimationFrame") ". On island disposal, "
         (code "register-in-scope") " auto-stops the loop.")

      (p "~140 lines. Depends on L0 (refs) and " (code "request-animation-frame")
         " from web/lib/browser.sx."))))
