import tkinter
from typing import Literal

WM_MOUSEMOVE = "WM_MOUSEMOVE"
WM_LBUTTONDOWN = "WM_LBUTTONDOWN"
WM_LBUTTONUP = "WM_LBUTTONUP"
WM_LBUTTONDBLCLK = "WM_LBUTTONDBLCLK"
WM_RBUTTONDOWN = "WM_RBUTTONDOWN"
WM_RBUTTONUP = "WM_RBUTTONUP"
WM_RBUTTONDBLCLK = "WM_RBUTTONDBLCLK"
WM_MBUTTONDOWN = "WM_MBUTTONDOWN"
WM_MBUTTONUP = "WM_MBUTTONUP"
WM_MBUTTONDBLCLK = "WM_MBUTTONDBLCLK"

WM_EVENT = (WM_MOUSEMOVE,
            WM_LBUTTONDOWN, WM_LBUTTONUP, WM_LBUTTONDBLCLK,
            WM_RBUTTONDOWN, WM_RBUTTONUP, WM_RBUTTONDBLCLK,
            WM_MBUTTONDOWN, WM_MBUTTONUP, WM_MBUTTONDBLCLK)

ICON_APPLICATION = "application"
ICON_ASTERISK = "asterisk"
ICON_ERROR = "error"
ICON_EXCLAMATION = "exclamation"
ICON_HAND = "hand"
ICON_QUESTION = "quesiton"
ICON_INFORMATION = "information"
ICON_WARNING = "warning"
ICON_WINLOGO = "winlogo"

ICONS = ("application", "asterisk", "error", "exclamation", "hand", "question", "information", "warning", "winlogo")


def download_winico():
    """
    安装所需要的一些文件资源。
    """
    from sys import executable
    from os.path import exists, split
    from time import sleep
    tcl = split(executable)[0] + "\\tcl\\"
    if exists(tcl):
        if not exists(tcl + "Winico64"):
            print("已经检测到tcl目录存在，准备开始下载...")
            sleep(3)
            import requests
            import zipfile
            import tempfile
            print("开始下载")

            def Get_Data():
                Url = "https://xiangqinxi.github.io/Winico/Winico64.zip"
                Response = requests.get(Url)
                return Url, Response.content

            Url, Data = Get_Data()  # data为byte字节

            _Tmp_File = tempfile.TemporaryFile()  # 创建临时文件

            _Tmp_File.write(Data)  # byte字节数据写入临时文件
            # _tmp_file.seek(0)

            ZipFile = zipfile.ZipFile(_Tmp_File, mode='r')
            for Names in ZipFile.namelist():
                File = ZipFile.extract(Names, tcl)  # 解压到zip目录文件下
                print("已经解压完成文件 ： " + File)
            ZipFile.close()
            print("下载完毕")
        else:
            print("已经检测到下载文件")
    print("准备开始安装")
    sleep(3)
    from os import rmdir
    import shutil
    try:
        shutil.move(tcl + 'Winico64\\pkg', tcl)
        shutil.move(tcl + 'Winico64\\src', tcl)
    except shutil.Error:
        print("你已经安装好，无需再次安装")
    else:
        print("安装完成！")
    shutil.rmtree(tcl + 'Winico64\\')


class DevTray(object):
    def __init__(self, master: tkinter.Tk, text: str = "托盘图标", icon=None, menu_func=None, use_winico: bool = True, auto_install: bool = True):
        """
        使用tcl扩展winico制作的托盘图标组件。

        :param master: 设置父组件。
        :param text: 设置托盘图标上的提示文本，默认是"托盘图标"。
        :param icon: 设置托盘图标上的图标图片，默认是winico的"tkchat.ico"，需要使用createfrom转换，或使用load获取图标。
        :param menu_func: 设置托盘图标的事件。返回给你三个参数，event事件名，x为X坐标，y为Y坐标。
        :param use_winico: 选择是否启用自动Winico。如果取消，之后还可以使用use_winico()方法启用。
        :param auto_install: 选择是否自动下载Winico，如果未检测到主文件，将会开始下载。
        """
        from os.path import exists, split
        from sys import executable
        if auto_install:
            if not exists(split(executable)[0] + "\\tcl\\pkg\\pkgIndex.tcl"):
                download_winico()
        self._master = master
        self._text = text
        if use_winico:
            self.use_winico()
        if icon is None:
            from os.path import split
            from sys import executable
            self._icon = self.createfrom(split(executable)[0] + "\\tcl\\pkg\\tkchat.ico")
        else:
            self._icon = icon
        if menu_func is None:
            self._menu_func = self.menu
        else:
            self._menu_func = menu_func

    @property
    def master(self):
        """
        父组件
        """
        return self._master

    @master.setter
    def master(self, master):
        self._master = master

    @property
    def text(self):
        """
        提示文本
        """
        return self._text

    @text.setter
    def text(self, text: str):
        self._text = text

    @property
    def icon(self):
        """
        图标
        """
        return self._icon

    @icon.setter
    def icon(self, icon):
        self._icon = icon

    @property
    def menu_func(self):
        """
        事件处理
        """
        return self._menu_func

    @menu_func.setter
    def menu_func(self, menu_func):
        self._menu_func = menu_func

    def use_winico(self):
        """
        使用winico组件
        """
        self._master.tk.call('package', 'require',
                             'Winico')

    def application(self):
        """
        从系统获取的应用程序图标
        """
        return self.load(ICON_APPLICATION, None)

    def asterisk(self):
        """
        从系统获取的信息图标
        """
        return self.load(ICON_ASTERISK, None)

    def error(self):
        """
        从系统获取错误图标
        """
        return self.load(ICON_ERROR, None)

    def exclamation(self):
        """
        从系统获取感叹号图标
        """
        return self.load(ICON_EXCLAMATION, None)

    def hand(self):
        """
        从系统获取手图标
        """
        return self.load(ICON_HAND, None)

    def question(self):
        """
        从系统获取疑问号图标
        """
        return self.load(ICON_QUESTION, None)

    def information(self):
        """
        从系统获取通知图标
        """
        return self.load(ICON_INFORMATION, None)

    def winlogo(self):
        """
        从系统获取Logo图标
        """
        return self.load(ICON_WINLOGO, None)

    def waring(self):
        """
        从系统获取错误图标
        """
        return self.load(ICON_WARNING, None)

    def createfrom(self, icon):
        """
        创建图标，返回图标
        """
        return self._master.tk.call('winico', 'createfrom',
                                    icon)

    def taskbar(self):
        """
        用于将图标加入托盘，但是需要安装winico，如果没安装，请使用download_winico()安装
        """
        self._master.tk.call('winico', 'taskbar', 'add', self._icon,
                             '-callback', (self._master.register(self._menu_func), '%m', '%x', '%y'),
                             '-pos', 0,
                             '-text', self._text)

    def load(self, resourcename, filename=None):
        """
        用于加载一些可执行文件上的资源。
        """
        return self._master.tk.call('winico', 'load', resourcename, filename)

    def setwindow(self, windowid, size="big"):
        """
        :param windowid: 设置主窗口，可以是Tk窗口，可以是窗柄。注意：必须映射窗口。如果不是，则可能会失败或崩溃。
        :param size: 用于调整大小，默认是big，可选small。
        """
        self._master.tk.call('winico', 'setwindow', windowid, size, )

    show = taskbar

    def info(self):
        """
        获取组件的托盘ID与信息
        """
        return self._master.tk.call("winico", "info")

    def delete(self, id):
        """
        删除托盘图标
        :param id: 为删除托盘图标的ID，可以使用info()获取到。
        """
        return self._master.tk.call("winico", "delete", id)

    def delete_me(self):
        """
        删除自己
        """
        return self._master.tk.call("winico", "delete", self.info())

    def menu(self, event, x, y):
        """
        内置菜单，用于初始化。
        """
        if event == WM_RBUTTONDOWN:
            menu = tkinter.Menu(tearoff=False)
            menu.add_command(label="退出", command=self.master.quit)
            menu.tk_popup(x, y)


if __name__ == '__main__':
    Window = tkinter.Tk()
    Tray = DevTray(Window)
    Tray.icon = Tray.information()
    Tray.taskbar()
    Window.mainloop()