import hid
import time
import sys
from typing import Optional

def wait_for_hid_device(vid: int, pid: int, descriptive_name: str, timeout_sec: int) -> Optional[hid.Device]:
    if(hasattr(hid, "HIDException")):
        hid_exception = hid.HIDException
    else:
        hid_exception = OSError
    print('Connecting to {}'.format(descriptive_name))
    if(timeout_sec > 1):
        print('Waiting up to {} seconds'.format(timeout_sec))
    for i in range(timeout_sec):
        try:
            retval = hid.Device(vid=vid, pid=pid)
            if(timeout_sec > 1):
                print('')
            return retval
        except(hid_exception):
            # continue waiting
            pass
        time.sleep(1.0)
        if(i < timeout_sec - 1):
            print('...',end='')
            sys.stdout.flush()
    if(timeout_sec > 1):
        print('')
    return None

def wait_10_sec():
    for i in range(10):
        print('waiting {}/10 seconds'.format(i+1))
        time.sleep(1.0)

if __name__ == "__main__":
    go_back_to_app = False
    # attempt connection to bootloader
    bootl = wait_for_hid_device(0x35BD, 0x4004, "Bootloader", 1)
    if(bootl is None):
        # try the Beyond and switch to bootloader
        bynd = wait_for_hid_device(0x35BD, 0x0101, "Beyond", 1)
        if(bynd is None):
            print("ERROR: No Beyond device detected")
            sys.exit()
        bynd.send_feature_report(bytes([0,ord('B')]))
        go_back_to_app = True
        print('Attempting to enter bootloader')
        bootl = wait_for_hid_device(0x35BD, 0x4004, "Bootloader", 20)
        if(bootl is None):
            print("ERROR: Could not connect to bootloader")
            sys.exit()
    
    # send "get version" query
    bootl.write(bytes([0,ord('*')]))

    # read response
    resp = bootl.read(65, timeout=100)

    if(len(resp) > 0):
        if(resp[0] == ord('*')):
            # echo response means no bootloader version number present
            print('No version number found')
        else:
            print('*** Version: {} ***'.format(resp.rstrip(bytes([0])).decode('ascii')))
    else:
        print('ERROR: No response from version number query')

    if(go_back_to_app):
        bootl.write(bytes([0, ord('B')]))