package de.duehl.basics.datetime.time;

import de.duehl.basics.datetime.time.watch.StopWatch;

/*
 * Copyright 2019 Christian Dühl. All rights reserved.
 *
 * This program is free software. You can redistribute it and/or
 * modify it under the same terms as perl:
 *
 * general:  http://dev.perl.org/licenses/
 * GPL:      http://dev.perl.org/licenses/gpl1.html
 * artistic: http://dev.perl.org/licenses/artistic.html
 */

import de.duehl.basics.text.NumberString;
import de.duehl.basics.text.Text;

/**
 * Diese Klasse misst den Zeitverbrauch zu regelmäßigen Zeitpunkten nach so und so vielen
 * eingelesenen oder verarbeiteten Datensätzen.
 *
 * @version 1.01     2019-11-26
 * @author Christian Dühl
 */

public class ContinousTimeMeasurement {

    /** Gibt an, dass noch keine Zeitmessung stattgefunden hat. */
    private static final long NO_TIME_MEASURING_YET = -1;

    /** Anzahl der Sekunden bei der letzten vorgenommenen Zeitmessung. */
    private long secondsOfLastTimeMeasurement;

    /**
     * Anzahl der Sekunden bei der ersten Zeitmessung oder -1, wenn nich keine stattgefunden hat.
     */
    private long secondsOfFirstTimeMeasurement;

    /** Misst die Laufzeit. */
    private final StopWatch watch;

    /** Konstruktor. */
    public ContinousTimeMeasurement() {
        secondsOfLastTimeMeasurement = 0;
        secondsOfFirstTimeMeasurement = NO_TIME_MEASURING_YET;
        watch = new StopWatch();
    }

    /** Startet die Zeitmessung. */
    public void startTimeMeasuring() {
        watch.start();
    }

    /** Beendet die TZeitmessung, danach darf nicht mehr timeMeasurement() aufgerufen werden! */
    public void stopTimeMeasuring() {
        watch.stop();
    }

    /** Wird aufgerufen, wann immer die Zeitmessung nach X Datensätzen vorgenommen wird. */
    public String timeMeasurement() {
        if (watch.isStopped()) {
            throw new RuntimeException("Nicht timeMeasurement() nach stopTimeMeasuring() aufrufen!");
        }

        StringBuilder builder = new StringBuilder();

        builder.append(watch.getTime())
                .append(" (")
                ;

        long secondsOfActualTimeMeasurement = watch.getTimeInSeconds();
        long secondsDifference = secondsOfActualTimeMeasurement - secondsOfLastTimeMeasurement;
        secondsOfLastTimeMeasurement = secondsOfActualTimeMeasurement;
        String difference = TimeHelper.secondsToHoursMinutesSeconds(secondsDifference);

        builder.append(difference);

        if (NO_TIME_MEASURING_YET == secondsOfFirstTimeMeasurement) {
            secondsOfFirstTimeMeasurement = secondsOfActualTimeMeasurement;
            builder.append(" - 1. Messung");
        }
        else {
            String percentOfFirstMeasurement = NumberString.percent(secondsDifference,
                    secondsOfFirstTimeMeasurement);
            builder.append(" - ")
                    .append(Text.fillWithSpacesAtFront(percentOfFirstMeasurement, 9))
                    .append("%")
                    ;
        }

        builder.append(")");

        return builder.toString();
    }

    /** Gibt die bisherige oder nach der Durchführung die gesamte Laufzeit zurück. */
    public String getRuntime() {
        return watch.getTime();
    }

}
