from psychopy import core, event, logging, visual
from psychopy_mri_emulator import launchScan

from reprostim.qr.psychopy import EventType, QrCode, QrConfig, QrStim

logging.console.setLevel(logging.INFO)


# common functions
def generate_sim_responses(
    n_series: int = 3,
    pulses_per_series: int = 5,
    intra_pulse_delay: float = 0.2,
    inter_series_delay: float = 3.0,
    initial_delay: float = 2.0,
    key: str = "5",  # default MRI trigger key
):
    """
    Generate simResponses for PsychoPy's launchScan.

    Parameters
    ----------
    n_series : int
        Number of series (blocks of pulses).
    pulses_per_series : int
        Number of pulses in each series.
    intra_pulse_delay : float
        Delay between pulses within a series (seconds).
    inter_series_delay : float
        Delay between consecutive series (seconds).
    initial_delay : float
        Delay before the first series starts (seconds).
    key : str
        Key name to simulate (default '5', typical for scanner triggers).

    Returns
    -------
    list of (float, str)
        A list suitable for simResponses.
    """
    sim_responses = [(0.0, "0")]  # initial dummy response
    t = initial_delay

    for _s in range(n_series):
        for _p in range(pulses_per_series):
            sim_responses.append((t, key))
            t += intra_pulse_delay
        t += inter_series_delay  # pause before next series

    return sim_responses


# Create a window
win = visual.Window([800, 600], fullscr=False)

# Optionally specify a QR code config
qr_config = QrConfig(
    scale=0.3,
    duration=1.0,
    fill_color="blue",
    back_color="transparent",
)


# Create a global clock to sync
globalClock = core.Clock()

# Generate simulated series parameters
n_series = 3
pulses_per_series = 5
intra_pulse_delay = 0.2
inter_series_delay = 3.0
initial_delay = 2.0
sim_responses = generate_sim_responses(
    n_series,
    pulses_per_series,
    intra_pulse_delay,
    inter_series_delay,
    initial_delay,
    key="5",
)
n_pulses = n_series * pulses_per_series

# MRI scanner settings
MR_settings = {
    "TR": 1000.0,  # time between volumes (sec)
    "volumes": n_pulses,  # number of volumes to simulate
    "sync": "5",  # key representing scanner pulse
    "skip": n_pulses,
    "sound": False,
}

logging.info("Starting fMRI scan emulator in test series mode")
logging.info(
    f"Simulating {n_series} series of {pulses_per_series} pulses each "
    f"({n_pulses} total)"
)
# logging.debug(f"simResponses: {sim_responses}")

# Display a QR code indicating the start of the session
qr = QrStim(win, QrCode(EventType.SESSION_START), qr_config)
qr.draw()
win.flip()
qr.wait()
win.flip()


seq = 0
# Wait for first sync pulse (Test mode will generate them automatically)
seq += launchScan(
    win,
    MR_settings,
    globalClock=globalClock,
    simResponses=sim_responses,
    mode="Test",
    log=True,
)
logging.info(f"Pulse[0], initial detected at {globalClock.getTime():.3f} sec")

# Main loop to react to pulses
while True:
    keys = event.getKeys()
    if MR_settings["sync"] in keys:
        logging.info(f"Pulse[{seq}] detected at {globalClock.getTime():.3f} sec")
        seq += 1
        if seq >= MR_settings["volumes"]:
            logging.info("All volumes acquired.")
            break
    if "escape" in keys:
        logging.info("Experiment terminated by user (Escape pressed)")
        break

# Display a QR code indicating the start of the session
qr = QrStim(win, QrCode(EventType.SESSION_END), qr_config)
qr.draw()
win.flip()
qr.wait()
win.flip()


logging.info("Done.")
win.close()
core.quit()
