import hid
from hid import HIDException

import time
import sys
import enum
import struct

BIGSCREEN_VID = 0x35BD
BEYOND_PID = 0x0101

DEFAULT_HID_TIMEOUT = 10

HMD_GET_SW_VER = ord('*')
HMD_GET_BOARD_SERIAL = ord('%')
HMD_GET_VXR_FIRMWARE = ord('N')
HMD_GET_OLED_ID = ord('^')
HMD_GET_USAGE_TIMER = ord('Z')
HMD_GET_CONFIG = ord('U')
HMD_ERROR = ord('E')

# "wait_for_response" is a helper function that waits for a specific message type
# the HID response packet (aka the HID report) has the message type as the first byte
# send the desired message types in a list of ints, any message that 
# matches one of the types in the list will be returned
# if timeout, returns empty bytes
#
# params:
# hmd_device -      A hid.Device object that is already connected to the HMD
# message_types -   List of ints, each int is a message type. If any message
#                   is received that matches one of the types, this function
#                   will return with that response packet
# timeout_ms -      An int with the desired timeout in milliseconds. Default 1000 
#
# Returns:  A bytes object. If timed out, will be empty bytes (b''). Otherwise
#           it will have the first message that matched one of the types given.

def wait_for_response(hmd_device: hid.Device, message_types:list, timeout_ms: int = 1000) -> bytes:
    start_time = time.monotonic_ns()
    
    while( (start_time + (timeout_ms*1000000)) > time.monotonic_ns()):
        bytesout = hmd_device.read(65, timeout=DEFAULT_HID_TIMEOUT)
        if(len(bytesout) > 0):
            if(bytesout[0] in message_types):
                return bytesout
    
    return b''


def get_config(hmd_device:hid.Device):
    full_config = []

    for i in range(16):

        hmd_device.send_feature_report(bytes([0, HMD_GET_CONFIG, i]))

        this_config_page = wait_for_response(hmd_device, [HMD_ERROR, HMD_GET_CONFIG])
        if(this_config_page[0] == HMD_GET_CONFIG):
            full_config.extend([bb for bb in this_config_page[2:34]])
    return full_config        

def save_config_to_file(filename: str, full_config:list[int]):
    with open(filename, 'w') as fil:
        for i in range(int(512 / 32)):
            fil.write(''.join(['{:02X}'.format(bb) for bb in full_config[32*i: 32*i + 32]]))
            fil.write('\n')

def main():
    bynd = hid.Device(vid=BIGSCREEN_VID, pid=BEYOND_PID)
    full_conf = get_config(bynd)
    save_config_to_file('current_config.txt', full_conf)

if __name__ == '__main__':
    main()