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

package net.ranides.assira.time;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import java.util.Timer;
import java.util.TimerTask;
import javax.swing.SwingUtilities;
import net.ranides.assira.trace.ExceptionInspector;

/**
 *
 * @author ranides
 * @todo (migration) assira
 */
@SuppressWarnings({"PMD.ShortVar"})
public final class TimeUtils {

    private TimeUtils() { }

    public static final long SECOND   = 1000;
    public static final long MINUTE   = 60 * SECOND;
    public static final long HOUR     = 60 * MINUTE;
    public static final long DAY      = 24 * HOUR;

    public static long diff(Date from, Date to) {
        return to.getTime() - from.getTime();
    }

    public static float diff(Date from, Date to, long unit) {
        return ( to.getTime() - from.getTime() ) / (float)unit;
    }

    public static void sleep(int ms) {
        try {
            Thread.sleep(ms);
        } catch (InterruptedException cause) {
            throw ExceptionInspector.rethrow(cause);
        }
    }

    public static String format(Date date, String format, String ddefault) {
        if(null == date) {
            return ddefault;
        }
        return new SimpleDateFormat(format, Locale.ROOT).format(date);
    }

    /**
     * Use caliper library instead
     * @param repeats
     * @param function
     * @return
     * @deprecated
     */
    @Deprecated
    public static TimeResult benchmark(int repeats, Runnable function) {
        TimeStack timer = new TimeStack();
        Runnable empty = new Runnable(){ @Override public void run() { /* do nothing */ } };

        timer.start();
        for(int i=0; i<repeats; i++) { empty.run(); }
        long t1 = timer.stop();

        timer.start();
        for(int i=0; i<repeats; i++) { function.run(); }
        long t2 = timer.stop();

        return new TimeResult(repeats, t1, t2);
    }
    
    public static TimerTask runAfterUI(int ms, final TimerTask action) {
        return runAfterUI(ms, new Runnable() {
            @Override
            public void run() { action.run(); }
        });
    }
    
    public static TimerTask runAfterUI(int ms, final Runnable action) {
        return runAfter(ms, new Runnable(){
            @Override
            public void run() { SwingUtilities.invokeLater(action); }
        });
    }
    
    public static TimerTask runAfter(int ms, final Runnable action) {
        return runAfter(ms, new TimerTask() { 
            @Override
            public void run() { action.run(); } 
        });
    }

    public static TimerTask runAfter(int ms, TimerTask action) {
        Li.TIMER.schedule(action, ms);
        return action;
    }
    
    public static <Q> AutoTimerTask<Q> runRepeat(int count, int delay, Q param, AutoTimerTask<Q> task) {
        return task.apply(false, count, param).schedule(delay);
    }
    
    public static <Q> AutoTimerTask<Q> runRepeatUI(int count, int delay, Q param, AutoTimerTask<Q> task) {
        return task.apply(true, count, param).schedule(delay);
    }
    
    static final class Li { // NOPMD - lazy init idiom
        static final Timer TIMER = new Timer("Assira TimeUtils",true);
    }

}
