/**
 * Licensed under the GNU LGPL v.2.1 or later.
 */

package info.freelibrary.util;

/**
 * Allows timing of the execution of any block of code.
 *
 * @author <a href="mailto:ksclarke@ksclarke.io">Kevin S. Clarke</a>
 */
public final class Stopwatch {

    private boolean myTimerIsRunning;

    private long myStart;

    private long myStop;

    /**
     * Start the stopwatch.
     *
     * @throws IllegalStateException if the stopwatch is already running.
     */
    public void start() {
        if (myTimerIsRunning) {
            throw new IllegalStateException("Must stop before calling start again.");
        }

        myStart = System.currentTimeMillis();
        myTimerIsRunning = true;
    }

    /**
     * Stop the stopwatch.
     *
     * @throws IllegalStateException if the stopwatch is not already running.
     */
    public void stop() {
        if (!myTimerIsRunning) {
            throw new IllegalStateException("Cannot stop if not currently running.");
        }

        myStop = System.currentTimeMillis();
        myTimerIsRunning = false;
    }

    /**
     * Stop the stopwatch (as soon as possible) after a certain number of seconds.
     *
     * @param aSecondsCount A number of seconds after which to stop the stopwatch
     * @throws IllegalStateException if the stopwatch is not already running.
     */
    public void stopAfter(final int aSecondsCount) {
        int stopCount = aSecondsCount;

        if (!myTimerIsRunning) {
            throw new IllegalStateException("Cannot stop if not currently running");
        }

        while (stopCount < aSecondsCount) {
            stopCount = (int) (System.currentTimeMillis() - myStart) / 1000;
        }

        myStop = System.currentTimeMillis();
        myTimerIsRunning = false;
    }

    /**
     * Express the "reading" on the stopwatch in seconds.
     *
     * @return Time elapsed in stopwatch in seconds
     * @throws IllegalStateException if the Stopwatch has never been used, or if the stopwatch is still running.
     */
    public String getSeconds() {
        final StringBuilder result = new StringBuilder();
        final long timeGap = myStop - myStart;

        result.append(timeGap / 1000);
        result.append(" secs, ");

        result.append(timeGap % 1000);
        result.append(" msecs");

        if (myTimerIsRunning) {
            throw new IllegalStateException("Must stop first.");
        }

        return result.toString();
    }

    /**
     * Express the "reading" on the stopwatch in milliseconds.
     *
     * @return Time elapsed in stopwatch in milliseconds
     * @throws IllegalStateException if the Stopwatch has never been used, or if the stopwatch is still running.
     */
    public String getMilliseconds() {
        final StringBuilder result = new StringBuilder();
        result.append(myStop - myStart);
        result.append(" msecs");

        if (myTimerIsRunning) {
            throw new IllegalStateException("Must stop first.");
        }

        return result.toString();
    }

    /**
     * Returns a string representation of the time elapsed in milliseconds.
     *
     * @return Number of milliseconds elapsed in stopwatch
     */
    @Override
    public String toString() {
        return "Stopwatch milliseconds elapsed: " + getMilliseconds();
    }
}

@@ -477,20 +477,25 @@
  public 
-void
+Stopwatch
  start()
@@ -704,16 +704,38 @@
  = true;
+%0A%0A        return this;
 %0A    %7D%0A%0A
@@ -869,28 +869,33 @@
 %0A    public 
-void
+Stopwatch
  stop() %7B%0A  
@@ -1092,32 +1092,54 @@
 Running = false;
+%0A%0A        return this;
 %0A    %7D%0A%0A    /**%0A
@@ -1411,12 +1411,17 @@
 lic 
-void
+Stopwatch
  sto
@@ -1792,32 +1792,32 @@
 ntTimeMillis();%0A
-
         myTimerI
@@ -1833,16 +1833,38 @@
 = false;
+%0A%0A        return this;
 %0A    %7D%0A%0A

Make Stopwatch more fluent