#!/usr/bin/env python
# coding:utf-8

from copy import deepcopy

import time
from threading import Thread
from Queue import Queue, Empty
from os import getenv, system
from PyQt4.QtGui import QWidget, QLineEdit, QPixmap, QLabel

from PyQt4.QtCore import SIGNAL, SLOT, Qt, QString, QEvent, pyqtSlot, QEventLoop, QBasicTimer
from PyQt4.QtCore import QTimer

from PyQt4.QtNetwork import QHostAddress
from common.info_dialog import InfoDialog
from ui_qss.winDesktopUnitQss import WinDesktopUnitQss, VmOsType
from time import sleep
# from usbip.usbip import UsbIp_Mgr
from usbip.usbipManage import UsbIpManage
from usbip.detectUSB import USBMessageBox
from WaitingDialog import WaitingDialog

from messageDialog import MessageDialog

from logger.logrecord import LogRecord

from usbip.usbipManage2 import UsbIp_Mgr as UsbIp_Mgr2


class WinDesktopUnit(WinDesktopUnitQss):
    '''WinDesktopUnit'''

    def __init__(self, userInfo, centerIp, vmInfo):
        super(WinDesktopUnit, self).__init__(None)
        try:
            # 备注，增加参数检查
            self.__userInfo = userInfo
            self.__centerIp = centerIp
            self.__vmInfo = vmInfo

            self.__usbip_connect_ip = ""

            self.osName.setText(self.__vmInfo["name"])  # 初始化 虚拟机名称
            self.osName.setAlignment(Qt.AlignCenter)
            self.vm_name_temp2 = self.__vmInfo["name"]
            # 初始化 虚拟机状态


            from sendCmd.validate.virtMachine import VirtMachine

            self.__vm = VirtMachine(self.__vmInfo, self.__userInfo, centerIp)
            self.__usbIpReconnectFlag = False  # usb 重新连接

            self.waitingdlg = WaitingDialog()

            # from WaitingLabel import WaitingLabel
            # self.waitingLabel = WaitingLabel(None, self)
            # self.waitingLabel.lower()
            # self.waitingLabel.hide()
            self.connect(self, SIGNAL('usbFailedSignal'), self.__on_usb_failed)
            self.connect(self, SIGNAL("waitingdlghide"), self.waitingdlgHide)
            self.connect(self, SIGNAL("waitingdlgClose"), self.waitingdlg, SLOT("close()"))
            self.connect(self, SIGNAL("waitingdlgMsg"), self.waitingdlg_showMsg)
            self.connect(self, SIGNAL("showErrMsg"), self.showErrMsg)
            self.connect(self, SIGNAL("openVm"), self, SLOT("openVmSlot()"))
            # # self.connect(self,SIGNAL("openVm"),self.openVmSlot)

            self.setOsImage(self.__vmInfo["osType"])  # 根据操作系统类型 指定系统图标

            # self.__bandSignalSlot()  # 绑定信号和槽

            self.__state_flag = False

            # self.__timer = QBasicTimer()
            # self.__timer.start(10000, self)

            self.getVMstateFunc()  # 刷新虚拟机 开关机 图标状态

        except Exception:
            LogRecord.instance().logger.exception("异常")
            raise Exception("桌面初始化异常")

    def waitingdlgHide(self):
        self.waitingdlg.hide()
        self.waitingdlg.movie.stop()

    def getVMstateFunc(self):

        if self.__vmInfo["osStatus"] == "down":
            self.setOsImage_OFF()

        elif self.__vmInfo["osStatus"] == "up":
            self.setOsImage_ON()

    # ---------------------------------------------
    # 刷新 虚拟机信息
    # ---------------------------------------------
    def vminfoupdate(self, vminfoList):
        for i in range(len(vminfoList)):
            if vminfoList[i]["vmId"] == self.__vmInfo["vmId"]:
                # print ""
                # print "---------  vm info update  ----------------"
                # print self.__vmInfo

                self.__vmInfo["osStatus"] = vminfoList[i]["osStatus"]
                self.__vmInfo["vmIp"] = vminfoList[i]["vmIp"]
                self.__vmInfo["vmPort"] = vminfoList[i]["vmPort"]
                self.__vmInfo["vmDomain"] = vminfoList[i]["vmDomain"]
                self.__vmInfo["guestAddress"] = vminfoList[i]["guestAddress"]
                self.__vmInfo["hostId"] = vminfoList[i]["hostId"]
                self.__vm.vmInfoUpdate(self.__vmInfo)  # 更新,虚拟机 信息
                self.getVMstateFunc()

                # 检查　usb Ip server 状态 并且释放进程　资源
                if UsbIp_Mgr2.usbIpServer_check() != 0:
                    LogRecord.instance().logger.error("usbip-server 已经停止运行")

                if self.__vm.vmIsUsed():
                    print self.__vmInfo["name"], "is used ------"
                    self.usbIpConnect()  # 启动usbip连接
                else:
                    self.usbIpDisConnect() # 添加 判断 连接ip 和 本机 ip 相同

    # 断开本机 ip 连接
    def usbIpDisConnect(self):
        ip = UsbIp_Mgr2.usb_getConnectIP()
        if ip in self.__vmInfo["guestAddress"]:
            UsbIp_Mgr2.usb_disconnect()
            self.__usbip_connect_ip =  ""

    def usbIpConnect(self):
        # 检查 开关机状态 usbip重现连接
        try:
            if self.__vmInfo["osStatus"] == "up":  # 如果虚拟机 为 up
                #  查询usbip的连接状态，确定是否重连, ip地址变化
                if UsbIp_Mgr2.usb_CheckStatus() != 0 \
                      or self.__usbip_connect_ip not in self.__vmInfo["guestAddress"]:

                    if len(self.__vmInfo["guestAddress"]) == 0:
                        LogRecord.instance().logger.error("usbip guestAddress is Null")
                        return  None

                    info = "usbip guestAddress %s " % str(self.__vmInfo["guestAddress"])
                    LogRecord.instance().logger.info(info)

                    # usb ip　连接
                    status,ip = UsbIp_Mgr2.usb_connect_guestAddres(self.__vmInfo["guestAddress"])
                    if status == 100: # 如果　usb server 未启动 ,则重启usb server
                        LogRecord.instance().logger.warn("usbip server 未启动,重启usbip-server")
                        UsbIp_Mgr2.usbIpServer_check() # 清理僵尸进程
                        UsbIp_Mgr2.usbIpServer_run()   # 重新启动　server
                        # status,ip = UsbIp_Mgr2.usb_connect_guestAddres(self.__vmInfo["guestAddress"])
                        # if status != 0:
                        #     LogRecord.instance().logger.error("usbip 连接失败")
                    elif status == 0:
                        self.__usbip_connect_ip = ip
                        LogRecord.instance().logger.info("usbip 连接成功" + str(ip))

                    else:
                        LogRecord.instance().logger.error("usbip 连接失败")

        except Exception:
            LogRecord.instance().logger.exception("usbip connect ")


    # 操作虚拟机
    def vmOprateSlot(self, vmid, cmd):
        if cmd == "exitAllVm":
            LogRecord.instance().logger.warn("exitAllVm, user be logout, exit vm!")
            self.__vm.exitVm()  # 退出 虚拟机 (关闭 Window)

        if vmid == self.__vmInfo["vmId"]:  # 重启 虚拟机
            if cmd == "reboot":
                res  = self.__vm.VMReboot() # 重启
                if res[0] == True:
                    LogRecord.instance().logger.info("Reboot vm seccess: " + str(vmid))
                else:
                    LogRecord.instance().logger.info("Reboot vm Faile : " + str(vmid))
            elif cmd == "poweroff":  # 断电
                res = self.__vm.VMPoweroff()
                if res[0] == True:
                    LogRecord.instance().logger.info("poweroff vm seccess: " + str(vmid))
                else:
                    LogRecord.instance().logger.info("poweroff vm Faile : " + str(vmid))

            elif cmd == "shutdown": # 关机
                res = self.__vm.VMShutdown()
                if res[0] == True:
                    LogRecord.instance().logger.info("shutdown vm seccess: " + str(vmid))
                else:
                    LogRecord.instance().logger.info("poweroff vm Faile : " + str(vmid))

            elif cmd == "enterVm":  # 进入 虚拟机
                LogRecord.instance().logger.info("Enter Default vm : " + str(vmid))
                self.__enterVirtMachine()
            elif cmd == "exitVm":  # 退出 虚拟机 (关闭 Window)
                LogRecord.instance().logger.info("Exit Default vm : " + str(vmid))
                self.__vm.exitVm()

    # 虚拟机重启
    def for_vm_reset(self, vmid):
        print "this is vmid", vmid
        print "this is self.vmid", self.__vmInfo['vmId']
        if vmid == self.__vmInfo["vmId"]:  # 重启 虚拟机
            for i in range(3):
                ret = self.__vm.VMReboot()
                if ret[0] == True:
                    break

    # ******************************************
    #            进入虚拟机
    # ******************************************
    def __enterVirtMachine(self):

        print "VMID = %s" % self.__vmInfo["vmId"]
        # 1 . 判断虚拟机 类型
        if self.__vmInfo["type"] != "spice":
            msg = "虚拟机配置异常： %s " % self.__vmInfo["type"]
            InfoDialog.instance().Information(u'提示', str(msg))  #
            return None

        if self.__vm.vmIsUsed() == True:
            InfoDialog.instance().Information(u'提示', "虚拟机已经打开")  #
            return None

        # --------------------------------------------------
        # 启动线程,查询等待 虚拟机状态准备
        # -------------------------------------------------
        def enterVmGetReady():  # 进入虚拟机准备工作
            try:
                # sleep(7)  # 确保 关机状态更新
                res = self.__vm.getSingleVMInfo()  # 有待优化，　三次容错．
                if res[0] == True:
                    self.__vmInfo = deepcopy(res[1])
                else:
                    LogRecord.instance().logger.error(res[1])

                if self.__vmInfo["osStatus"] != "up" and self.__vmInfo["osStatus"] != "powering_up" \
                        and self.__vmInfo["osStatus"] != "down":
                    self.emit(SIGNAL("waitingdlgMsg"), "%s" % str(self.__vmInfo["osStatus"]))
                    sleep(5)  # 延时
                    self.emit(SIGNAL("showErrMsg"), "虚拟机状态异常，请联系管理员")
                    return None

                if self.__vmInfo["osStatus"] == "down":
                    res = self.__vm.VMPowerOn()
                    if res[0] == False:
                        LogRecord.instance().logger.error(res[1])
                        info = "开机失败: " + str(res[1])
                        if len(info) > 15:
                            info = "虚拟机运行出错，请联系管理员！"
                        self.emit(SIGNAL("waitingdlgMsg"), info)
                        sleep(3)  # 延时
                        # self.emit(SIGNAL("showErrMsg"), info)
                        return None
                    else:
                        LogRecord.instance().logger.debug("开机命令,发送成功")
                        self.waitingdlg.showMsg("正在开机...")

                # 1. 等待虚拟机 开机ing/开机
                sleep(1)
                for i in range(30):
                    if self.__vmInfo["osStatus"] == "up" or self.__vmInfo["osStatus"] == "powering_up":
                        break
                    sleep(1)

                if self.__vmInfo["osStatus"] != "up" and self.__vmInfo["osStatus"] != "powering_up":
                    self.emit(SIGNAL("waitingdlgMsg"), "开机失败! %s" % self.__vmInfo["osStatus"])
                    sleep(5)  # 延时
                    self.emit(SIGNAL("showErrMsg"), "开机失败, 超时!")
                    return

                # 2.  检查端口
                for i in range(30):
                    if self.__vmInfo["vmPort"] != None:
                        break
                    if i >= 29:
                        self.emit(SIGNAL("waitingdlgMsg"), "开机失败,Port=null")
                        sleep(5)
                        self.emit(SIGNAL("showErrMsg"), "开机失败, 端口为空!")
                        return None
                    sleep(1)

                # 3. 开启虚拟机 初始化
                res = self.__vm.openVmInit()
                if res[0] == False:
                    print res[1]
                    # 发送信号
                    self.emit(SIGNAL("waitingdlgMsg"), res[1])
                    sleep(5)  # 延时
                    return None
                else:
                    self.emit(SIGNAL("openVm"), res[1])  # 发送开机信号
                    sleep(2)  # 延时 等地 虚拟开机

            except Exception as e:
                LogRecord.instance().logger.exception("异常")
            finally:
                print "关闭 等待窗口"
                self.emit(SIGNAL("waitingdlghide"))

        self.timer = Thread(target=enterVmGetReady)
        self.timer.setDaemon(True)  # 设置主线程为非守护线程

        # # QTimer.singleShot(2000, self.__loginEventLop, SLOT(quit())); # 2000ms

        self.waitingdlg.showFullScreen()  # 进入 虚拟机等待窗口 显示
        self.waitingdlg.showMsg("正在进入虚拟机...")
        self.timer.start()
        # self.waitingdlg.exec_()  # 进入 虚拟机等待窗口 显示

    # 显示错误信息
    @pyqtSlot()
    def showErrMsg(self, msg):
        # MessageDialog(str(msg)).exec_()
        InfoDialog.instance().Information(u'提示', str(msg))  #

    # 进入虚拟机等待显示
    @pyqtSlot()
    def waitingdlg_showMsg(self, msg):
        self.waitingdlg.showMsg(str(msg))

    # --------------------------------------
    # 打开虚拟机
    # --------------------------------------
    @pyqtSlot()
    def openVmSlot(self):
        if self.__vm.vmIsUsed() == True:
            InfoDialog.instance().Information(u'提示', "虚拟机已经打开")  #
            return None

        print self.__vmInfo
        if self.__vmInfo["vmPort"] == None:
            print "----------开机失败,端口为空------------,", self.__vmInfo["vmPort"]
            self.emit(SIGNAL("showErrMsg"), "开机失败, 端口为空!")
            return None

        # 1. 进入虚拟机
        # self.__vm.vmInfoUpdate(self.__vmInfo) # 刷新 port
        print "------------进入虚拟机--------", self.__vmInfo

        #add by pbc for usb status -top
        from common import common_run
        ret = common_run.get_usb_set_statu()
        if ret == "00":
            common_run.usb_status = "virt_ip"
        elif ret == "11":
            common_run.usb_status = "network_ip"
        #add by pbc for usb status -end
        UsbIp_Mgr2.usb_disconnect() # 断开连接
        res = self.__vm.openVm()
        if res[0] == False:
            InfoDialog.instance().Information(u'提示', str(res[1]))  #
            return None

        # ----------------------- 将状态标记为 已经登录 -------------------------------
        from sendCmd.validate.userValidate import UserValidate
        userValidate = UserValidate(self.__userInfo, self.__centerIp)
        # 将状态标记为 已经登录
        res = userValidate.setSessionState_loged()

        if res == False:
            info = "请求更新会话状态: %s" % str(res[1])
            InfoDialog.instance().Information(u'警告', info)  #
            return None

        UsbIp_Mgr2.usb_disconnect() # 断开连接
        time.sleep(0.01)
        self.usbIpConnect()
        # # ----------------------- usbip 连接 -------------------------------
        # if len(self.__vmInfo["guestAddress"]) >= 1:
        #     # print "------------- usbIp 连接----", self.__vmInfo["guestAddress"][0]
        #     self.__usbIpReconnectFlag = True
        #
        #     info = "usbip guestAddress %s " % str(self.__vmInfo["guestAddress"])
        #     LogRecord.instance().logger.info(info)
        #
        #     __info = "start usbip connect  [%s] "  % str(self.__vmInfo["guestAddress"][0])
        #     LogRecord.instance().logger.info(__info)
        #     UsbIpManage.usb_connect_Ext(self.__vmInfo["guestAddress"],30*60)
        #     # UsbIpManage.usb_connect3(self.__vmInfo["guestAddress"])
        # else:
        #     LogRecord.instance().logger.error("usbip guestAddress is Null")

    #def __isUSBCorrect(self):
    #    """
    #    判断USB连接是否正常
    #    :return:是/否
    #    """
    #    try:
    #        connectedIP = UsbIpManage.get_connected_ip()
    #        if connectedIP == None:
    #            LogRecord.instance().logger.debug("connectedIP == None")
    #            return False
    #        else:
    #            LogRecord.instance().logger.debug("connectedIP: " + connectedIP)
    #            for addr in self.__vmInfo["guestAddress"]:
    #                if connectedIP == str(addr):
    #                    LogRecord.instance().logger.debug("usbip连接状态正常！")
    #                    return True
    #            LogRecord.instance().logger.error("usbip连接状态异常！")
    #        if not self.__usbIpReconnectFlag:
    #            LogRecord.instance().logger.debug("usbip不是正常连接状态，断开连接！")
    #            UsbIpManage.usb_disconnect()
    #    except Exception, err:
    #        LogRecord.instance().logger.exception("更新usbip连接状态异常！")
    #    return False

    def __on_usb_failed(self):
        USBMessageBox.showMsg(u'USB设备透传连接异常，请联系管理员！\n（请按“Ctrl+Alt”键，从虚拟机中释放鼠标）')

    def __USB_plugin_thread(self):
        if not self.__vm.vmIsUsed():  # 如果虚拟机 没有使用 则返回
            return
        if self.__vmInfo["osStatus"] == "up":  # 如果虚拟机 为 up
            # if not self.__isUSBCorrect():
            #     time.sleep(6.0)  # 添加延迟6秒再次判断usbip连接状态
            #     if not self.__isUSBCorrect():
            #         self.emit(SIGNAL('usbFailedSignal'))
            if UsbIp_Mgr2.usb_CheckStatus() == 0:
                return
            time.sleep(6.0)  # 添加延迟6秒再次判断usbip连接状态
            if UsbIp_Mgr2.usb_CheckStatus() == 0:
                return
            self.emit(SIGNAL('usbFailedSignal'))

    def onUSBPlugin(self):
        """
        处理USB设备插入信号
        :return:
        """
        usbThread = Thread(target=self.__USB_plugin_thread)
        usbThread.setDaemon(True)
        usbThread.start()

    @pyqtSlot()
    def enterVmImage(self):  #
        super(WinDesktopUnit, self).enterVmImage()

    # 鼠标按下事件
    def mousePressEvent(self, event):
        self.background_press()
        LogRecord.instance().logger.info("mousePressEvent")
        if event.buttons() == Qt.LeftButton:
            self.__enterVirtMachine()  # 进入虚拟机

    # 鼠标抬起 事件
    def mouseReleaseEvent(self, event):
        self.background_border()
        if event.buttons() == Qt.LeftButton:
            pass


###############################
#   单元测试
##############################
if __name__ == "__main__":

    import os, sys

    _dirs = os.path.abspath(__file__)  # 当前文件路径
    _dirs = os.path.dirname(_dirs)  # 当前文件目录
    _dirs = os.path.dirname(_dirs)  # 上级文件路径
    sys.path.append(_dirs)  #

    from PyQt4 import QtGui
    from os import environ

    environ["WIN_UI_IMAGES_PATH"] = "../../images"
    environ["LOG_STDOUT"] = "stdout"  #
    app = QtGui.QApplication([])

    userInfo = {
        "userName": "wr",
        "userPassword": "+qwy5z1KTSk=",
    }
    vmInfo = {
        "vmId": "96e8d7f1-510d-4484-a079-6be1a3928241",
        "name": "abcdef",
        "osType": "windows_xp",
        "osStatus": "up",  # "down",
        "vmIp": "",
        "vmPort": "",
        "vmPassWd": ""
    }

    try:
        win = WinDesktopUnit(userInfo, "192.168.102.33", vmInfo)
        win.show()
        app.exec_()

    except Exception as e:
        LogRecord.instance().logger.exception("异常")
