import sys


if sys.platform == "win32":
    import logging
    import ctypes
    from ctypes.wintypes import LONG, HKEY, LPCWSTR, DWORD, BOOL, HANDLE, LPVOID

    LPSECURITY_ATTRIBUTES = LPVOID

    RegOpenKeyEx = ctypes.windll.advapi32.RegOpenKeyExW
    RegOpenKeyEx.restype = LONG
    RegOpenKeyEx.argtypes = [HKEY, LPCWSTR, DWORD, DWORD, ctypes.POINTER(HKEY)]

    RegCloseKey = ctypes.windll.advapi32.RegCloseKey
    RegCloseKey.restype = LONG
    RegCloseKey.argtypes = [HKEY]

    RegNotifyChangeKeyValue = ctypes.windll.advapi32.RegNotifyChangeKeyValue
    RegNotifyChangeKeyValue.restype = LONG
    RegNotifyChangeKeyValue.argtypes = [HKEY, BOOL, DWORD, HANDLE, BOOL]

    CloseHandle = ctypes.windll.kernel32.CloseHandle
    CloseHandle.restype = BOOL
    CloseHandle.argtypes = [HANDLE]

    CreateEvent = ctypes.windll.kernel32.CreateEventW
    CreateEvent.restype = BOOL
    CreateEvent.argtypes = [LPSECURITY_ATTRIBUTES, BOOL, BOOL, LPCWSTR]

    WaitForSingleObject = ctypes.windll.kernel32.WaitForSingleObject
    WaitForSingleObject.restype = DWORD
    WaitForSingleObject.argtypes = [HANDLE, DWORD]

    ERROR_SUCCESS = 0x00000000

    KEY_READ = 0x00020019
    KEY_QUERY_VALUE = 0x00000001

    REG_NOTIFY_CHANGE_NAME = 0x00000001
    REG_NOTIFY_CHANGE_LAST_SET = 0x00000004

    WAIT_OBJECT_0 = 0x00000000
    WAIT_TIMEOUT = 0x00000102

class RegistryMonitor:

    def __init__(self, root, subkey):
        self._root = root
        self._subkey = subkey
        self._event = CreateEvent(None, False, False, None)

        self._key = None
        self._open_key()
        if self._key:
            self._set_key_update_notification()

    def close(self):
        CloseHandle(self._event)
        if self._key:
            RegCloseKey(self._key)
            self._key = None

    def is_updated(self):
        wait_result = WaitForSingleObject(self._event, 0)

        # previously watched
        if wait_result == WAIT_OBJECT_0:
            self._set_key_update_notification()
            return True

        # no changes or no key before
        if wait_result != WAIT_TIMEOUT:
            # unexpected error
            logging.warning("Unexpected WaitForSingleObject result %s", wait_result)
            return False

        if self._key is None:
            self._open_key()

        if self._key is not None:
            self._set_key_update_notification()

        return False

    def _set_key_update_notification(self):
        filter_ = REG_NOTIFY_CHANGE_NAME | REG_NOTIFY_CHANGE_LAST_SET
        status = RegNotifyChangeKeyValue(self._key, True, filter_, self._event, True)
        if status != ERROR_SUCCESS:
            # key was deleted
            RegCloseKey(self._key)
            self._key = None

    def _open_key(self):
        access = KEY_QUERY_VALUE | KEY_READ
        self._key = HKEY()
        rc = RegOpenKeyEx(self._root, self._subkey, 0, access, ctypes.byref(self._key))
        if rc != ERROR_SUCCESS:
            self._key = None