import numpy as np
import array
import json
import asyncio
import nest_asyncio
from pylsl import StreamInfo, StreamOutlet
from pupil_labs.real_time_screen_gaze import marker_generator
from pupil_labs.realtime_api.simple import discover_one_device
from pupil_labs.real_time_screen_gaze.gaze_mapper import GazeMapper

# Marker definieren
#marker_pixels = marker_generator.generate_marker(marker_id=np.arange(15))

# Marker-Koordinaten
# marker_verts = {
#     0: [(66, 66), (130, 66), (130, 130), (66, 130)],
#     1: [(66, 303), (130, 303), (130, 367), (66, 367)],
#     2: [(66, 540), (130, 540), (130, 604), (66, 604)],
#     3: [(66, 777), (130, 777), (130, 841), (66, 841)],
#     4: [(66, 1014), (130, 1014), (130, 1078), (66, 1078)],
#     5: [(513, 66), (577, 66), (577, 130), (513, 130)],
#     6: [(960, 66), (1024, 66), (1024, 130), (960, 130)],
#     7: [(1407, 66), (1471, 66), (1471, 130), (1407, 130)],
#     8: [(513, 1014), (577, 1014), (577, 1078), (513, 1078)],
#     9: [(960, 1014), (1024, 1014), (1024, 1078), (960, 1078)],
#     10: [(1407, 1014), (1471, 1014), (1471, 1078), (1407, 1078)],
#     11: [(1858, 66), (1922, 66), (1922, 130), (1858, 130)],
#     12: [(1858, 303), (1922, 303), (1922, 367), (1858, 367)],
#     13: [(1858, 540), (1922, 540), (1922, 604), (1858, 604)],
#     14: [(1858, 777), (1922, 777), (1922, 841), (1858, 841)],
#     15: [(1858, 1014), (1922, 1014), (1922, 1078), (1858, 1078)],
# }
marker_verts = {
    0: [(83, 83), (147, 83), (147, 147), (83, 147)],
    1: [(83, 311.5), (147, 311.5), (147, 375.5), (83, 375.5)],
    2: [(83, 540), (147, 540), (147, 604), (83, 604)],
    3: [(83, 768.5), (147, 768.5), (147, 832.5), (83, 832.5)],
    4: [(83, 997), (147, 997), (147, 1061), (83, 1061)],
    5: [(521.5, 83), (585.5, 83), (585.5, 147), (521.5, 147)],
    6: [(960, 83), (1024, 83), (1024, 147), (960, 147)],
    7: [(1.3985e+03, 83), (1469, 83), (1469, 147), (1.3985e+03, 147)],
    8: [(521.5, 997), (585.5, 997), (585.5, 1061), (521.5, 1061)],
    9: [(960, 997), (1024, 997), (1024, 1061), (960, 1061)],
    10: [(1.3985e+03, 997), (1469, 997), (1469, 1061), (1.3985e+03, 1061)],
    11: [(1837, 83), (1901, 83), (1901, 147), (1837, 147)],
    12: [(1837, 311.5), (1901, 311.5), (1901, 375.5), (1837, 375.5)],
    13: [(1837, 540), (1901, 540), (1901, 604), (1837, 604)],
    14: [(1837, 768.5), (1901, 768.5), (1901, 832.5), (1837, 832.5)],
    15: [(1837, 997), (1901, 997), (1901, 1061), (1837, 1061)],
}

# Bildschirmgröße
screen_size = (1920, 1080)

def run_in_executor(loop, func, *args):
    return loop.run_in_executor(None, func, *args)

async def discover_device():
    loop = asyncio.get_running_loop()
    device = await run_in_executor(loop, discover_one_device)
    return device

async def main():
    # Gerät entdecken und kalibrieren
    device = discover_one_device(max_search_duration_seconds=12) # statt await discover_device()
    calibration = device.get_calibration()
    gaze_mapper = GazeMapper(calibration)

    # Bildschirmfläche hinzufügen
    screen_surface = gaze_mapper.add_surface(marker_verts, screen_size)

    # LSL-Stream einrichten
    info = StreamInfo('Gaze', 'Gaze', 2, 100, 'float32', 'myuid34234')
    outlet = StreamOutlet(info)
    print('outlet')
    print(outlet)

    # Hauptschleife
    while True:
        frame, gaze = device.receive_matched_scene_video_frame_and_gaze()
        #print('frame')
        #print(frame)
        #print('gaze')
        #print(gaze)
        result = gaze_mapper.process_frame(frame, gaze) # Fehler: result is empty
        #print('result')
        #print(result)
        print('.')
        for surface_gaze in result.mapped_gaze[screen_surface.uid]:
            print('GAZE COORDINATES')
            gaze_coordinates = [surface_gaze.x, surface_gaze.y]
            outlet.push_sample(gaze_coordinates)
            print(f"Gaze at {surface_gaze.x}, {surface_gaze.y}")
# Event-Loop anpassen und ausführen
nest_asyncio.apply()
asyncio.get_event_loop().run_until_complete(main())







