from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *
import notify2
import sys
import os
import time
import threading as thd
import tushare as ts
import Txt2Png


class Mythread(QThread):
    # 定义信号,定义参数为str类型
    _signal = pyqtSignal()

    def __init__(self):
        super(Mythread, self).__init__()

    def run(self):
        while True:
            # 发出信号通知主线程
            self._signal.emit()
            # 让程序休眠
            time.sleep(2)


class Start:
    # 实时行情
    df = []
    # 托盘集合
    tpList = []
    # 最新price集合，用于和前后两次比较
    priceList = []
    # 提示上下限
    myPriceList = []
    # 是否有弹过提示
    notifyList = []
    # 行情时间
    current_time = ''

    def update_ui(self):
        # 计算时间，如果开市时间则去获取行情
        s = self.current_time.split(':')
        if len(s) > 1:
            # print(s[0])
            h = int(s[0])
            if h < 9 or 13 > h >= 12 or h >= 15:
                return

        # print('running')
        # 获取实时行情
        self.df = ts.get_realtime_quotes(self.codes)

        for i in self.df.index:
            # 昨收盘价
            pre = self.df.loc[i]['pre_close']
            # 当前时间
            self.current_time = self.df.loc[i]['time']
            # 当前价
            p = self.df.loc[i]['price']
            # 小数点后有3位，舍弃最后一位
            price = p[0:len(p) - 1]
            # 如果本次得到的price和上一次不一样，则刷新托盘图标
            if price != self.priceList[i]:
                # 记录变动后的新price
                self.priceList[i] = price

                # 转成图标
                Txt2Png.Price2Png(i, price, pre)

                # 刷新托盘图标
                self.tpList[i].setIcon(QIcon(str(i)+'.png'))

                # 判断是否需要提示
                if self.notifyList[i] is False:
                    price = float(self.df.loc[i]['price'])
                    pre = float(self.df.loc[i]['pre_close'])
                    percent = (price - pre) / pre * 100
                    # 检查预警上限
                    if price >= self.myPriceList[i]['max']:
                        self.show_message(self.df.loc[i]['name'], '恭喜！已达预期值' + str(self.myPriceList[i]['max']))
                        self.notifyList[i] = True
                    # 检查预警下限
                    elif price <= self.myPriceList[i]['min']:
                        self.show_message(self.df.loc[i]['name'], '小心！已到预警线' + str(self.myPriceList[i]['min']))
                        self.notifyList[i] = True
                    # 波动大于5个点需要提示
                    elif abs(percent) >= 5:
                        self.show_message(self.df.loc[i]['name'], str(format(percent, '.2f') + '%，注意波动！！！'))
                        self.notifyList[i] = True

    # 弹出提示
    def show_message(self, title, content):
        notify2.init('notify'+title)
        bubble = notify2.Notification(title, content)
        bubble.show()

    # 打开详情窗
    def show_window(self):
        # self.tpList[0].showMessage("提示", "你点了消息", icon=0)

        # 关闭所有窗口,也不关闭应用程序
        QApplication.setQuitOnLastWindowClosed(False)

        # QWidget窗口是PyQt5中所有用户界口对象的基本类.我们使用了QWidget默认的构造器.默认的构造器没有父类.一个没有父类的窗口被称为一个window.
        self.w = QWidget()
        # resize()方法调整了窗口的大小.被调整为250像素宽和250像素高.
        self.w.resize(1000, 100)
        # move()方法移动了窗口到屏幕坐标x=300, y=300的位置.
        self.w.move(300, 300)
        # 在这里我们设置了窗口的标题.标题会被显示在标题栏上.
        self.w.setWindowTitle('List')

        # 创建一个底layout
        form_layout = QFormLayout()

        # 标题
        layout = QHBoxLayout()
        layout.addWidget(QLabel('名称(代码)'))
        layout.addWidget(QLabel('当前价'))
        layout.addWidget(QLabel('百分比'))
        layout.addWidget(QLabel('最高价'))
        layout.addWidget(QLabel('最低价'))
        layout.addWidget(QLabel('开盘价'))
        layout.addWidget(QLabel('昨收价'))
        layout.addWidget(QLabel('成交量'))
        layout.addWidget(QLabel('成交额'))
        # 添加一行
        form_layout.addRow(layout)

        for i in self.df.index:
            price = float(self.df.loc[i]['price'])
            pre = float(self.df.loc[i]['pre_close'])
            percent = format((price - pre) / pre * 100, '.2f')

            name = self.df.loc[i]['name']
            code = self.df.loc[i]['code']
            high = format(float(self.df.loc[i]['high']), '.2f')
            low = format(float(self.df.loc[i]['low']), '.2f')
            open = format(float(self.df.loc[i]['open']), '.2f')
            volume = self.df.loc[i]['volume']
            amount = self.df.loc[i]['amount']

            layout = QHBoxLayout()
            layout.addWidget(QLabel(name+'\n('+code+')'))
            layout.addWidget(QLabel(str(price)))
            layout.addWidget(QLabel(str(percent)+' %'))
            layout.addWidget(QLabel(high))
            layout.addWidget(QLabel(low))
            layout.addWidget(QLabel(open))
            layout.addWidget(QLabel(str(pre)))
            layout.addWidget(QLabel(volume))
            layout.addWidget(QLabel(amount))
            # 间距为0
            layout.setSpacing(0)
            # 添加一行
            form_layout.addRow(layout)

        self.w.setLayout(form_layout)

        # show()方法将窗口显示在屏幕上.一个窗口是先在内存中被创建,然后显示在屏幕上的.
        self.w.show()

    def quit_app(self):
        # 关闭窗体程序
        QCoreApplication.instance().quit()
        # 在应用程序全部关闭后，TrayIcon其实还不会自动消失，
        # 直到你的鼠标移动到上面去后，才会消失，
        # 这是个问题，（如同你terminate一些带TrayIcon的应用程序时出现的状况），
        # 这种问题的解决我是通过在程序退出前将其setVisible(False)来完成的。
        for i in range(len(self.tpList)):
            self.tpList[i].setVisible(False)
            # 删除生成托盘图标
            os.remove(str(i)+'.png')

    def __init__(self, codes, myPriceList):

        # 要关注的代码
        self.codes = codes
        self.myPriceList = myPriceList

        # 初始化提示状态
        for i in range(len(self.codes)):
            self.notifyList.append(False)

        # pyqt窗口必须在QApplication方法中使用
        # 每一个PyQt5应用都必须创建一个应用对象.sys.argv参数是来自命令行的参数列表.Python脚本可以从shell里运行.这是我们如何控制我们的脚本运行的一种方法.
        app = QApplication(sys.argv)

        # 设置系统托盘图标的菜单
        menu = QMenu()
        a1 = QAction('&显示(Show)', triggered=self.show_window)  # 直接退出可以用qApp.quit
        a2 = QAction('&退出(Exit)', triggered=self.quit_app)  # 直接退出可以用qApp.quit
        menu.addAction(a1)
        menu.addAction(a2)

        for i in range(len(self.codes)):
            # 在系统托盘处显示图标
            tp = QSystemTrayIcon()
            tp.setIcon(QIcon('./bg.png'))

            # 设置右键弹出菜单
            tp.setContextMenu(menu)

            # 不调用show不会显示系统托盘
            tp.show()

            # 添加托盘到list中
            self.tpList.append(tp)

            # 定义好要保存的最新price
            self.priceList.append('')

        # 创建线程
        self.thread = Mythread()
        # 注册信号处理函数
        self.thread._signal.connect(self.update_ui)
        # 启动线程
        self.thread.start()

        # sys为了调用sys.exit(0)退出程序
        # 最后,我们进入应用的主循环.事件处理从这里开始.主循环从窗口系统接收事件,分派它们到应用窗口.如果我们调用了exit()方法或者主窗口被销毁,则主循环结束.sys.exit()方法确保一个完整的退出.环境变量会被通知应用是如何结束的.
        # exec_()方法是有一个下划线的.这是因为exec在Python中是关键字.因此,用exec_()代替.
        sys.exit(app.exec_())


# if __name__ == "__main__":
#     Start(['000014', '002358'])

