 GENERIC: tick* ( delegate -- )
 GENERIC: draw* ( tick-slice delegate -- )
 
-SYMBOL: game-loop
-
-: since-last-tick ( loop -- nanos )
-    last-tick>> nano-count swap - ;
-
-: tick-slice ( loop -- slice )
-    [ since-last-tick ] [ tick-interval-nanos>> ] bi /f 1.0 min ;
-
-CONSTANT: MAX-FRAMES-TO-SKIP 5
-
 DEFER: stop-loop
 
 TUPLE: game-loop-error game-loop error ;

continuations destructors fry kernel math math.order memory
namespaces sequences specialized-vectors system
tools.memory ui ui.gadgets.worlds vm vocabs.loader arrays
benchmark.struct ;
IN: game.loop

TUPLE: game-loop
    { tick-interval-nanos integer read-only }
    tick-delegate
    draw-delegate
    { last-tick integer }
    { running? boolean }
    { tick# integer }
    { frame# integer }
    timer
    benchmark-data ;

STRUCT: game-loop-benchmark


: increment-tick ( loop -- )
    [ 1 + ] change-tick#
    drop ;

PRIVATE>

:: when-running ( loop quot -- )
    [
        loop
        dup running?>> quot [ drop ] if
    ] [
        loop game-loop-error
    ] recover ; inline

: tick-iteration ( loop -- )
    [ [ tick ] [ increment-tick ] bi ] when-running ;

: frame-iteration ( loop -- )
    [ redraw ] when-running ;

: start-loop ( loop -- )
    t >>running?

    dup
    [ '[ _ tick-iteration ] f ]
    [ tick-interval-nanos>> nanoseconds ] bi <timer> >>tick-timer

    dup '[ _ frame-iteration ] f 1 milliseconds <timer> >>draw-timer

    [ tick-timer>> ] [ draw-timer>> ] bi [ start-timer ] bi@ ;

: stop-loop ( loop -- )
    f >>running?
    [ tick-timer>> ] [ draw-timer>> ] bi [ stop-timer ] bi@ ;

: <game-loop*> ( tick-interval-nanos tick-delegate draw-delegate -- loop )
    f 0 0 f f
    game-loop-benchmark-vector{ } clone
    game-loop boa ;

