package com.inari.firefly.system.external;

import java.util.HashMap;
import java.util.Map;

public abstract class FFTimer {
    
    protected long lastUpdateTime, time, timeElapsed;
    
    private final Map<Float, UpdateScheduler> updateSchedulers;
    
    protected FFTimer() {
        lastUpdateTime = 0;
        time = 0;
        timeElapsed = 0;
        updateSchedulers = new HashMap<Float, UpdateScheduler>();
    }

    public final long getLastUpdateTime() {
        return lastUpdateTime;
    }

    public final long getTime() {
        return time;
    }

    public final long getTimeElapsed() {
        return timeElapsed;
    }
    
    public final void updateSchedulers() {
        for ( UpdateScheduler scheduler : updateSchedulers.values() ) {
            scheduler.update();
        }
    }

    public abstract void tick();
    
    public final UpdateScheduler createUpdateScheduler( float resolution ) {
        UpdateScheduler updateScheduler = updateSchedulers.get( resolution );
        if ( updateScheduler == null ) {
            updateScheduler = new UpdateScheduler( resolution );
            updateSchedulers.put( resolution, updateScheduler );
        }
        
        return updateScheduler;
    }

    @Override
    public String toString() {
        StringBuilder builder = new StringBuilder();
        builder.append( "FFTimer [lastUpdateTime=" );
        builder.append( lastUpdateTime );
        builder.append( ", time=" );
        builder.append( time );
        builder.append( ", timeElapsed=" );
        builder.append( timeElapsed );
        builder.append( "]" );
        return builder.toString();
    }

    public final class UpdateScheduler {
        
        private final float resolution;
        private final long delayMillis;
        private long lastUpdate = -1;
        private long tick = 0;
        private boolean needsUpdate;
        
        private UpdateScheduler( float resolution ) {
            this.resolution = resolution;
            delayMillis = (long) ( 1000 / resolution );
        }
        
        public final float getResolution() {
            return resolution;
        }

        public final long getTick() {
            return tick;
        }
        
        final void update() {
            if ( lastUpdateTime - lastUpdate >= delayMillis ) {
                lastUpdate = lastUpdateTime;
                tick++;
                needsUpdate = true;
            } else if ( needsUpdate ) {
                needsUpdate = false;
            }
        }

        public final boolean needsUpdate() {
            return needsUpdate;
        }
        
        public final void reset() {
            lastUpdate = -1;
            tick = 0;
        }

    }

}

@@ -86,16 +86,62 @@
 l.Map;%0A%0A
+import com.inari.commons.lang.list.DynArray;%0A%0A
 public a
@@ -292,16 +292,72 @@
 dulers;%0A
+    private final DynArray%3CUpdateScheduler%3E schedulers;%0A
     %0A   
@@ -512,24 +512,91 @@
 heduler%3E();%0A
+        schedulers = DynArray.create( UpdateScheduler.class, 20 );%0A
     %7D%0A%0A    p
@@ -875,65 +875,219 @@
 r ( 
-UpdateScheduler scheduler : updateSchedulers.values() ) %7B
+int i = 0; i %3C schedulers.capacity(); i++ ) %7B%0A            UpdateScheduler updateScheduler = schedulers.get( i );%0A            if ( updateScheduler == null ) %7B%0A                continue;%0A            %7D %0A            
 %0A   
@@ -1087,33 +1087,39 @@
    %0A            
-s
+updateS
 cheduler.update(
@@ -1429,32 +1429,32 @@
 ( resolution );%0A
-
             upda
@@ -1498,24 +1498,71 @@
 cheduler );%0A
+            schedulers.add( updateScheduler );%0A
         %7D%0A  

fix UpdateScheduler