"""The Virtual Time Tagger is used to replay stored FileWriter files.
From the user perspective, there is no difference between the time tag stream of the physical Time
Tagger and the stream generated by the Virtual Time Tagger from a file. In this example, we first
store the data of a physical Correlation measurement using the FileWriter and SynchronizedMeasurements.
Later, we are able to repeat the Correlation measurement and to adjust the measurement
parameters accordingly."""

from matplotlib import pyplot as plt
import os
import tempfile

from Swabian import TimeTagger


def request_values():
    """Request input for measurement and replay parameters and evaluate the user input."""
    parameters = dict()
    try:
        parameters["binwidth"] = max(1, int(input("-> Binwidth (ps): ")))
    except ValueError:
        print("Default value is used.")
    try:
        parameters["n_bins"] = max(1, int(input("-> Number of bins: ")))
    except ValueError:
        print("Default value is used.")
    try:
        speed = float(input("-> Replay speed (factor, <0 => max): "))
    except ValueError:
        print("No or bad input, we'll use a replay speed of 1")
        speed = 1
    try:
        begin = int(input("-> Begin replay at (ps): "))
    except ValueError:
        print("No or bad input, we'll start at the beginning = 0")
        begin = 1
    try:
        duration = int(input("-> Replay duration (ps, -1 = all): "))
    except ValueError:
        print("No or bad input, we'll replay all data.")
        duration = -1
    return parameters, speed, begin, duration


# Create a TimeTagger instance to control your hardware
tagger = TimeTagger.createTimeTagger()

# Activate test signal on channel 1 and 2
tagger.setTestSignal(1, True)
tagger.setTestSignal(2, True)

# We create a temporary folder as storage for the FileWriter files
tempdir = tempfile.TemporaryDirectory()
filename = tempdir.name + os.sep + "filewriter.ttbin"

# We synchronize the FileWriter to our Correlation measurement to run the
# repeated measurements on the very same set of time tags as the original one.
synchronized = TimeTagger.SynchronizedMeasurements(tagger=tagger)
corr = TimeTagger.Correlation(tagger=synchronized.getTagger(),
                              channel_1=1,
                              channel_2=2)
filewriter = TimeTagger.FileWriter(tagger=synchronized.getTagger(),
                                   filename=filename,
                                   channels=[1, 2])

# We let the measurements run for 10 s and watch the data accumulation
fig = plt.figure()
synchronized.startFor(int(1E13))
while synchronized.isRunning():
    fig.clear()
    plt.plot(corr.getIndex(), corr.getData())
    plt.xlabel("Time difference (ps)")
    plt.ylabel("Counts")
    plt.pause(.1)

# Now the data acquisition is done, and we can release the measurements
del synchronized
del corr
del filewriter
TimeTagger.freeTimeTagger(tagger)
del tagger

# The while loop allows us to repeat the replay several times
while True:
    print("\nInput data for the data replay")

    # The request_values function allows us to input our data
    corr_param, replay_speed, replay_begin, replay_duration = request_values()

    # The Virtual Time Tagger is initialized similar to the physical one.
    # It takes a file as its initial data source.
    virtual_tagger = TimeTagger.createTimeTaggerVirtual(filename=filename,
                                                        begin=replay_begin,
                                                        duration=replay_duration)

    # We can pass virtual_tagger to the "tagger" argument of any measurement class constructor
    corr_replay = TimeTagger.Correlation(tagger=virtual_tagger,
                                         channel_1=1,
                                         channel_2=2,
                                         **corr_param)

    # In general, the data are replayed at the same speed as they have been acquired.
    # You can modify the speed by a factor or replay them as fast es possible by speed < 0
    virtual_tagger.run(replay_speed)

    # To check if the replay is finished, use the waitUntilFinished method. If you want to do
    # something during the measurement (such as watching the accumulation), use a while loop and
    # timeout=0. If you just want to wait for completion, you can skip the loop and use
    # timeout=-1 instead.
    is_running = True
    while is_running:
        is_running = not virtual_tagger.waitUntilFinished(timeout=0)
        fig.clear()
        plt.plot(corr_replay.getIndex(), corr_replay.getData())
        plt.xlabel("Time difference (ps)")
        plt.ylabel("Counts")
        plt.pause(.1)

    # Ask if the user wants to repeat the replay with another set of parameters.
    cont = ""
    for i in range(3):
        cont = input("Try again? (y/n) ")
        if cont and cont in "ynYN":
            break
    if cont not in "yY":
        break

tempdir.cleanup()

TimeTagger.freeTimeTagger(virtual_tagger)
