/*
 * @author Ranides Atterwim <ranides@gmail.com>
 * @copyright Ranides Atterwim
 * @license WTFPL
 * @url http://ranides.net/projects/assira.drafts
 */

package net.ranides.assira.time;

import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import net.ranides.assira.collection.maps.IdentMap;

/**
 *
 * @author Ranides Atterwim <ranides@gmail.com>
 */
public final class TimeMetric {
    
    private static final Map<TimeUnit, String> UNITS = new IdentMap<>(
        new TimeUnit[]{TimeUnit.DAYS, TimeUnit.HOURS, TimeUnit.MICROSECONDS, TimeUnit.MILLISECONDS, TimeUnit.MINUTES, TimeUnit.NANOSECONDS, TimeUnit.SECONDS}, 
        new String[]{"d", "h", "us", "ms", "m", "ns", "s"}
    );
    
    private final TimeUnit unit;
    
    private final Deque<Long> stack = new ArrayDeque<>();
    
    public TimeMetric() {
        this(TimeUnit.MILLISECONDS);
    }

    public TimeMetric(TimeUnit unit) {
        this.unit = unit;
        start();
    }

    public TimeMetric start() {
        stack.push(System.nanoTime());
        return this;
    }
    
    public long stop() {
        return stop(unit);
    }
    
    public long stop(TimeUnit unit) {
        return time(unit, stack.pop());
    }

    public long time() {
        return time(unit);
    }
    
    public long time(TimeUnit unit) {
        return time(unit, stack.peek());
    }
    
    private long time(TimeUnit unit, long dt) {
        return unit.convert(System.nanoTime() -  dt, TimeUnit.NANOSECONDS);
    }

    @Override
    public String toString() {
        return time() + UNITS.get(unit);
    }
    
}
