package com.lasarobotics.ftc.util;

import java.util.HashMap;
import java.util.concurrent.TimeUnit;

/**
 * Created by Ehsan on 6/11/2015.
 */
public class Timers {
    private HashMap<String,Long> store;
    private long precision;
    public Timers(){
        precision = 5L;
    }
    public Timers(long precision){
        this.precision = precision;
    }
    public void startClock(String name){
        store.put(name,System.nanoTime());
    }
    public void resetClock(String name){
        if (store.containsKey(name)){
            store.put(name,System.nanoTime());
        }
        else{
            throw new IllegalArgumentException("Timers" + name + " does not exist.");
        }
    }

    /**
     * Get clock value. Defaults to millisecond precision.
     * @param name Name of the clock
     * @return Value of clock in milliseconds
     */
    public long getClockValue(String name){
        if (store.containsKey(name)){
           Long start = store.get(name);
           return TimeUnit.MILLISECONDS.convert(Math.abs(System.nanoTime()-start),TimeUnit.NANOSECONDS);
        }
        else{
            throw new IllegalArgumentException("Timers" + name + " does not exist.");
        }
    }

    /**
     * Get clock value with precision in a given time unit
     * @param name Name of the clock
     * @param timeUnit TimeUnit the output should be in
     * @return The value of the clock converted to the time unit specified (may loose precision)
     */
    public long getClockValue(String name,TimeUnit timeUnit){
        if (store.containsKey(name)){
            Long start = store.get(name);
            long nanoDiff = Math.abs(System.nanoTime() - start);
            return timeUnit.convert(nanoDiff,TimeUnit.NANOSECONDS);
        }
        else{
            throw new IllegalArgumentException("Timers" + name + " does not exist.");
        }
    }

    public boolean isAtTargetMillis(String name, long target){
        if (store.containsKey(name)){
            Long start = store.get(name);
            long milliDiff = TimeUnit.MILLISECONDS.convert(Math.abs(target - Math.abs(System.nanoTime()-start)),TimeUnit.NANOSECONDS);
            return milliDiff < precision;
        }
        else{
            throw new IllegalArgumentException("Timers" + name + " does not exist.");
        }
    }


    public long getPrecision() {
        return precision;
    }

    public void setPrecision(long precision) {
        this.precision = precision;
    }
}

@@ -50,19 +50,21 @@
 til.Hash
-Map
+table
 ;%0Aimport
@@ -107,37 +107,73 @@
 %0A * 
-Created by Ehsan on 6/11/2015
+Implements advanced timers with events and precision manipulation
 .%0A *
@@ -216,11 +216,13 @@
 Hash
-Map
+table
 %3CStr
@@ -250,20 +250,104 @@
 private 
-long
+int precision;%0A%0A    /**%0A     * Instantiates the timer class with the default millisecond
  precisi
@@ -344,25 +344,33 @@
 nd precision
-;
+.%0A     */
 %0A    public 
@@ -404,16 +404,178 @@
  = 5
-L
 ;%0A    %7D
+%0A%0A    /**%0A     * Instantiates the timer class with an arbitrary precision in milliseconds.%0A     * @param precision Precision of the clock, in milliseconds.%0A     */
 %0A   
@@ -589,20 +589,19 @@
  Timers(
-long
+int
  precisi
@@ -651,97 +651,360 @@
   %7D%0A
-    public void startClock(String name)%7B%0A        store.put(name,System.nanoTime());%0A    %7D
+%0A    /**%0A     * Start (and create, if nonexistent) a clock with a specified name.%0A     * @param name The clock name%0A     */%0A    public void startClock(String name)%7B%0A        store.put(name,System.nanoTime());%0A    %7D%0A%0A    /**%0A     * Reset a clock with the specified name.  Clock will continue running immediately.%0A     * @param name The clock name%0A     */
 %0A   
@@ -1195,33 +1195,33 @@
 Exception(%22Timer
-s
+ 
 %22 + name + %22 doe
@@ -1708,33 +1708,33 @@
 Exception(%22Timer
-s
+ 
 %22 + name + %22 doe
@@ -2008,17 +2008,16 @@
  (may lo
-o
 se preci
@@ -2374,33 +2374,33 @@
 Exception(%22Timer
-s
+ 
 %22 + name + %22 doe
@@ -2424,32 +2424,280 @@
        %7D%0A    %7D%0A%0A
+    /**%0A     * Returns whether the clock is at the specified amount of milliseconds%0A     * @param name The clock name%0A     * @param target The target time in milliseconds%0A     * @return True if at the target (+- precision), false otherwise%0A     */%0A
     public boole
@@ -3077,17 +3077,17 @@
 n(%22Timer
-s
+ 
 %22 + name
@@ -3136,69 +3136,290 @@
     
-public long getPrecision() %7B%0A        return precision;%0A    %7D%0A
+/**%0A     * Gets the precision in milliseconds%0A     * @return Precision in milliseconds%0A     */%0A    public long getPrecision() %7B%0A        return precision;%0A    %7D%0A%0A    /**%0A     * Sets the precision to a value%0A     * @param precision The precision of the clock, in milliseconds.%0A     */
 %0A   
@@ -3444,20 +3444,19 @@
 ecision(
-long
+int
  precisi

Document timers