# this implements a very basic auditory oddball task using PsychoPy
# which also sends markers over LSL at the moment of standard and deviant stimuli.
# see https://en.wikipedia.org/wiki/Oddball_paradigm for more details

from psychopy import prefs, visual, core, sound
from utilities import wait_for_space
import random
import pylsl

prefs.hardware['audioDevice'] = 'Speaker/HP (2- Realtek High Definition Audio)'

# Prepare the LSL stream info
info = pylsl.StreamInfo(
    name='Stimulus computer',
    type='Markers',
    channel_count=1,
    nominal_srate=0, # should be zero for markers
    channel_format='string',
    source_id=None,
)

# Create a new outlet
outlet = pylsl.StreamOutlet(info)

# Print the stream info
print("Now publishing stream:", info.name(), info.type(), info.channel_count(), "channels at", info.nominal_srate(), "Hz")

screen = visual.Window([800, 600], color='black', units='pix')
fixation = visual.TextStim(screen, text='+', color='white', height=50)
text_standard = visual.TextStim(screen, text='s', color='white', height=50)
text_deviant  = visual.TextStim(screen, text='d', color='white', height=50)
sound_standard = sound.Sound('A', octave=4, secs=0.5)  # standard sound stimulus
sound_deviant = sound.Sound('A', octave=5, secs=0.5)   # deviant sound stimulus

wait_for_space(screen, 'Press SPACE to start')
fixation.draw()
screen.flip()
core.wait(2)

# present 10 trials of the oddball task
for trial in range(150):

    condition = random.choice(['s', 's', 's', 's', 'd'])  # 80% standard, 20% deviant

    if condition == 's':
        print('standard')
        stimulus = sound_standard
        # text_standard.draw()
    else:
        print('deviant')
        stimulus = sound_deviant
        # text_deviant.draw()

    # screen.flip()
    outlet.push_sample(condition)
    stimulus.play()  # play the randomly chosen stimulus

    fixation.draw()
    screen.flip()
    jitter = random.uniform(0, 0.2)
    core.wait(0.9 + jitter)

wait_for_space(screen, 'Done, press SPACE to finish')

screen.close()
core.quit()