import hid
import time
import typing
import struct
from enum import IntEnum

DEFAULT_HID_TIMEOUT = 10
BIGSCREEN_VID = 0x35BD
BEYOND_PID = 0x0101

class Hid_Message(IntEnum):
    DUTY_CYCLE = ord('I')
    SUCCESS = ord('$')
    ERROR = ord('E')

def find_beyond_device():
    devices = hid.enumerate()
    beyond_devices = [d for d in devices if d['vendor_id'] == BIGSCREEN_VID and d['product_id'] == BEYOND_PID]
    if beyond_devices:
        return beyond_devices[0]['path']
    return None

def set_duty_cycle(value: int) -> bool:
    if(value > 1023):
        value = 1023
    if(value < 0):
        value = 0

    new_duty_lsb = int(value).to_bytes(2, 'little')[0]
    new_duty_msb = int(value).to_bytes(2, 'little')[1]
    device_path = find_beyond_device()
    if not device_path:
        return False
    beyond = hid.device()
    beyond.open_path(device_path)
    beyond.send_feature_report(bytes([0, Hid_Message.DUTY_CYCLE, new_duty_msb, new_duty_lsb]))
    hid_reply = wait_for_response(beyond, [Hid_Message.SUCCESS, Hid_Message.ERROR])
    beyond.close()

    if(len(hid_reply) > 0):
        if(hid_reply[0] == Hid_Message.SUCCESS):
            return True
    return False


def wait_for_response(beyond: hid.device, message_types: list[int], timeout_ms: int = 1000) -> bytes:
    start_time = time.monotonic_ns()

    while ((start_time + (timeout_ms * 1000000)) > time.monotonic_ns()):
        bytesout = beyond.read(65)
        if (len(bytesout) > 0):
            if (bytesout[0] in message_types):
                return bytes(bytesout)

    return b''