# Path: stagehand/utils.py
# def get_file_from_zip(root, filename, ims=None):
#     try:
#         zipfile, files = get_file_from_zip.zipfile, get_file_from_zip.files
#     except AttributeError:
#         get_file_from_zip.zipfile = zipfile = ZipFile(__loader__.archive)
#         get_file_from_zip.files = files = dict((i.filename, i) for i in get_file_from_zip.zipfile.infolist())
# 
#     # Don't use os.path.join here because zipfile uses / as a path sep even on
#     # Windows.
#     filename = (root.rstrip(os.path.sep) + '/' + filename).replace(os.path.sep, '/')
#     if filename not in files:
#         raise FileNotFoundError
# 
#     info = files[filename]
#     mtime = datetime(*info.date_time)
#     if ims and datetime.utcfromtimestamp(ims) >= mtime:
#         return info, mtime, None
#     else:
#         return info, mtime, zipfile.open(filename)
# 
# Path: stagehand/toolbox/utils.py
# def get_temp_path(appname):
#     try:
#         return get_temp_path.paths[appname]
#     except KeyError:
#         # create tmp directory for the user
#         base = gettempdir()
#         try:
#             user = getpass.getuser()
#         except Exception:
#             user = os.getuid()
#         path = os.path.join(base, '{}-{}'.format(appname, user))
#         if not os.path.isdir(path):
#             try:
#                 os.mkdir(path, 0o0700)
#             except OSError:
#                 # Probably the directory already exists.  Verify.
#                 if not os.path.isdir(path):
#                     raise IOError('Security Error: %s is not a directory, aborted' % path)
# 
#         # On non-Windows, verify the permissions.
#         if sys.platform != 'win32':
#             if os.path.islink(path):
#                 raise IOError('Security Error: %s is a link, aborted' % path)
#             if stat.S_IMODE(os.stat(path).st_mode) % 0o01000 != 0o0700:
#                 raise IOError('Security Error: %s has wrong permissions, aborted' % path)
#             if os.stat(path)[stat.ST_UID] != os.getuid():
#                 raise IOError('Security Error: %s does not belong to you, aborted' % path)
# 
#         get_temp_path.paths[appname] = path
#         return path
# 
# def tobytes(value, encoding=None, desperate=True, coerce=False, fs=False):
#     """
#     Convert (if necessary) the given value to a "string of bytes", agnostic to
#     any character encoding.
# 
#     :param value: the value to be converted to a string of bytes
#     :param encoding: the character set to first try to encode to; if None, will
#                      use the system default (from the locale).
#     :type encoding: str
#     :param desperate: if True and encoding to the given (or default) charset
#                       fails, will also try utf-8 and latin-1 (in that order),
#                       and if those fail, will encode to the preferred charset,
#                       replacing unknown characters with \\\\uFFFD.
#     :type desperate: bool
#     :param coerce: if True, will coerce numeric types to a bytes object; if
#                    False, such values will be returned untouched.
#     :type coerce: bool
#     :param fs: indicates value is a file name or other environment string; if True,
#                the encoding (if not explicitly specified) will be the encoding
#                given by ``sys.getfilesystemencoding()`` and the error handler
#                used will be ``surrogateescape`` if supported.
#     :type fs: bool
#     :returns: the value as a bytes object, or the original value if coerce is
#               False and the value was not a bytes or string.
#     """
#     if isinstance(value, bytes):
#         # Nothing to do.
#         return value
#     elif isinstance(value, (int, float)):
#         return bytes(str(value), 'ascii') if coerce else value
#     elif not isinstance(value, str):
#         # Need to coerce to a unicode before converting to bytes.  We can't just
#         # feed it to bytes() in case the default character set can't encode it.
#         value = tostr(value, coerce=coerce)
# 
#     errors = 'strict'
#     if fs:
#         if not encoding:
#             encoding = sys.getfilesystemencoding()
#         errors = 'surrogateescape'
# 
#     for c in (encoding or ENCODING, 'utf-8', 'latin-1'):
#         try:
#             return value.encode(c, errors)
#         except UnicodeError:
#             pass
#         if not desperate:
#             raise UnicodeError("Couldn't encode value to bytes (and not desperate enough to keep trying)")
# 
#     return value.encode(encoding or ENCODING, 'replace')


from sys import platform, exit
from ctypes import (windll, Structure, sizeof, WINFUNCTYPE, pointer, byref, c_uint, c_int, c_char, c_wchar)
from ctypes.wintypes import (HWND, HANDLE, HICON, HBRUSH, HMENU, POINT, LPCWSTR, WPARAM, LPARAM, MSG, RECT, DWORD, WORD)
from stagehand.config import config
from stagehand.utils import get_file_from_zip
from stagehand.toolbox.utils import get_temp_path, tobytes
import os
import asyncio
import webbrowser
import threading

        ('uCallbackMessage', c_uint),
        ('hIcon', HICON),
        ('szTip', c_wchar * 128),
        ('dwState', DWORD),
        ('dwStateMask', DWORD),
        ('szInfo', c_wchar * 256),
        ('uVersion', c_uint), # unioned with uTimeout
        ('szInfoTitle', c_wchar * 64),
        ('dwInfoFlags', DWORD),
        ('guidItem', GUID),
        ('hBalloonIcon', HICON)
    ]

user32.DefWindowProcW.argtypes = [HWND, c_uint, WPARAM, LPARAM]

ID_OPEN = 2000
ID_SETTINGS = 2001
ID_OPEN_TVDIR = 2002
ID_OPEN_LOGS = 2003
ID_EXIT = 2010


class Plugin:
    def __init__(self, manager):
        self.manager = manager
        self.hwnd = None
        self.running_event = threading.Event()

    def get_icon_path(self):
        try:

# Path: stagehand/utils.py
# def get_file_from_zip(root, filename, ims=None):
#     try:
#         zipfile, files = get_file_from_zip.zipfile, get_file_from_zip.files
#     except AttributeError:
#         get_file_from_zip.zipfile = zipfile = ZipFile(__loader__.archive)
#         get_file_from_zip.files = files = dict((i.filename, i) for i in get_file_from_zip.zipfile.infolist())
# 
#     # Don't use os.path.join here because zipfile uses / as a path sep even on
#     # Windows.
#     filename = (root.rstrip(os.path.sep) + '/' + filename).replace(os.path.sep, '/')
#     if filename not in files:
#         raise FileNotFoundError
# 
#     info = files[filename]
#     mtime = datetime(*info.date_time)
#     if ims and datetime.utcfromtimestamp(ims) >= mtime:
#         return info, mtime, None
#     else:
#         return info, mtime, zipfile.open(filename)
# 
# Path: stagehand/toolbox/utils.py
# def get_temp_path(appname):
#     try:
#         return get_temp_path.paths[appname]
#     except KeyError:
#         # create tmp directory for the user
#         base = gettempdir()
#         try:
#             user = getpass.getuser()
#         except Exception:
#             user = os.getuid()
#         path = os.path.join(base, '{}-{}'.format(appname, user))
#         if not os.path.isdir(path):
#             try:
#                 os.mkdir(path, 0o0700)
#             except OSError:
#                 # Probably the directory already exists.  Verify.
#                 if not os.path.isdir(path):
#                     raise IOError('Security Error: %s is not a directory, aborted' % path)
# 
#         # On non-Windows, verify the permissions.
#         if sys.platform != 'win32':
#             if os.path.islink(path):
#                 raise IOError('Security Error: %s is a link, aborted' % path)
#             if stat.S_IMODE(os.stat(path).st_mode) % 0o01000 != 0o0700:
#                 raise IOError('Security Error: %s has wrong permissions, aborted' % path)
#             if os.stat(path)[stat.ST_UID] != os.getuid():
#                 raise IOError('Security Error: %s does not belong to you, aborted' % path)
# 
#         get_temp_path.paths[appname] = path
#         return path
# 
# def tobytes(value, encoding=None, desperate=True, coerce=False, fs=False):
#     """
#     Convert (if necessary) the given value to a "string of bytes", agnostic to
#     any character encoding.
# 
#     :param value: the value to be converted to a string of bytes
#     :param encoding: the character set to first try to encode to; if None, will
#                      use the system default (from the locale).
#     :type encoding: str
#     :param desperate: if True and encoding to the given (or default) charset
#                       fails, will also try utf-8 and latin-1 (in that order),
#                       and if those fail, will encode to the preferred charset,
#                       replacing unknown characters with \\\\uFFFD.
#     :type desperate: bool
#     :param coerce: if True, will coerce numeric types to a bytes object; if
#                    False, such values will be returned untouched.
#     :type coerce: bool
#     :param fs: indicates value is a file name or other environment string; if True,
#                the encoding (if not explicitly specified) will be the encoding
#                given by ``sys.getfilesystemencoding()`` and the error handler
#                used will be ``surrogateescape`` if supported.
#     :type fs: bool
#     :returns: the value as a bytes object, or the original value if coerce is
#               False and the value was not a bytes or string.
#     """
#     if isinstance(value, bytes):
#         # Nothing to do.
#         return value
#     elif isinstance(value, (int, float)):
#         return bytes(str(value), 'ascii') if coerce else value
#     elif not isinstance(value, str):
#         # Need to coerce to a unicode before converting to bytes.  We can't just
#         # feed it to bytes() in case the default character set can't encode it.
#         value = tostr(value, coerce=coerce)
# 
#     errors = 'strict'
#     if fs:
#         if not encoding:
#             encoding = sys.getfilesystemencoding()
#         errors = 'surrogateescape'
# 
#     for c in (encoding or ENCODING, 'utf-8', 'latin-1'):
#         try:
#             return value.encode(c, errors)
#         except UnicodeError:
#             pass
#         if not desperate:
#             raise UnicodeError("Couldn't encode value to bytes (and not desperate enough to keep trying)")
# 
#     return value.encode(encoding or ENCODING, 'replace')


# Path: stagehand/platform/win32.py
from sys import platform, exit
from ctypes import (windll, Structure, sizeof, WINFUNCTYPE, pointer, byref, c_uint, c_int, c_char, c_wchar)
from ctypes.wintypes import (HWND, HANDLE, HICON, HBRUSH, HMENU, POINT, LPCWSTR, WPARAM, LPARAM, MSG, RECT, DWORD, WORD)
from stagehand.config import config
from stagehand.utils import get_file_from_zip
from stagehand.toolbox.utils import get_temp_path, tobytes
import os
import asyncio
import webbrowser
import threading

        ('uCallbackMessage', c_uint),
        ('hIcon', HICON),
        ('szTip', c_wchar * 128),
        ('dwState', DWORD),
        ('dwStateMask', DWORD),
        ('szInfo', c_wchar * 256),
        ('uVersion', c_uint), # unioned with uTimeout
        ('szInfoTitle', c_wchar * 64),
        ('dwInfoFlags', DWORD),
        ('guidItem', GUID),
        ('hBalloonIcon', HICON)
    ]

user32.DefWindowProcW.argtypes = [HWND, c_uint, WPARAM, LPARAM]

ID_OPEN = 2000
ID_SETTINGS = 2001
ID_OPEN_TVDIR = 2002
ID_OPEN_LOGS = 2003
ID_EXIT = 2010


class Plugin:
    def __init__(self, manager):
        self.manager = manager
        self.hwnd = None
        self.running_event = threading.Event()

    def get_icon_path(self):
        try:

            info, mtime, f = get_file_from_zip('data', 'win32tray.ico')
