# coding:utf-8
'''
Created on Nov 18, 2014

@author: raul
'''
from PyQt4.Qt import SLOT
from PyQt4.QtCore import QEventLoop, QTimer, SIGNAL, QUrl, QByteArray, QString, \
    QObject
from PyQt4.QtNetwork import QNetworkAccessManager, QNetworkRequest, \
    QSslConfiguration, QSslSocket, QSsl
from PyQt4.QtXml import QDomDocument

from common.User import User
from common.VmDict import VmDict, VM, Disk
from setting.logrecord import LogRecord


class NetUtil(QObject):
    '''
    Send request to server and retrieve data.
    Parse the data and convert it to a class
    '''
    _instance = None

    
    def __init__(self):
        '''
        Constructor
        '''
        super(NetUtil, self).__init__()
        self.__initiallize()
    
    def __initiallize(self):
        '''
        All properties of NetUtil
        '''
    
    def _getRequestContext(self, subUrl):
        '''
        @subUrl: sub url  
        '''
        netMgmt = QNetworkAccessManager()
        
        eventLoop = QEventLoop()
        timer = QTimer()
        timeout = 60 * 1000
        timer.setSingleShot(True)
        self.connect(netMgmt, SIGNAL("finished(QNetworkReply*)"), eventLoop,SLOT("quit()"))
        self.connect(timer, SIGNAL("timeout()"), eventLoop,SLOT("quit()"))
        
        self.serverUrl = User.instance().getUserServer()
        request = QNetworkRequest() 
        config = QSslConfiguration() 
        config.setPeerVerifyMode(QSslSocket.VerifyNone)
        config.setProtocol(QSsl.TlsV1)
        request.setSslConfiguration(config)
        strUrl = "https://" + User.instance().getUserServer() + subUrl
        request.setUrl(QUrl(strUrl))
        request.setRawHeader("Authorization", "Basic " + QByteArray(QString("%1:%2").arg(User.instance().name + "@" + User.instance().domain).arg(User.instance().passwd).toAscii()).toBase64())
        request.setRawHeader("Filter", "true")
        request.setRawHeader("isClient","true")
        reply = netMgmt.get(request)
        timer.start(timeout)
        eventLoop.exec_()
        
        requestInfo = reply.readAll()
        reply.deleteLater()
        dom = QDomDocument() 
        dom.setContent(requestInfo)
        return dom
    
    def __parseVm(self, dom, vmFlag=True):
        '''
        @param dom: DomDocument
        @return: vm class
        '''
        tag = "vm" if vmFlag else "template"
        vm_list = dom.elementsByTagName(tag)
        vmCount = len(vm_list)
        vmDict = VmDict.instance()
        vmDict.clear()
        for i in range(vmCount):
            v = VM()
            # QDomNode 
            node = vm_list.at(i)
            v.id = node.toElement().attribute("id")
            v.vmflag = vmFlag
            # QDomNodeList 
            itemlist = node.childNodes()
            for j in range(len(itemlist)):
                element = itemlist.at(j).toElement()
                tag = element.tagName()
                if tag == "name":
                    v.name = element.text()
                elif tag == 'description':
                    v.description = element.text()
                elif (tag == "type"):
                    v.type = element.text()
                elif tag == "ismonitor":
                    v.ismonitor = element.text()
                elif tag == "status":
                    status_c = len(element.childNodes())
                    for m in range(status_c):
                        status_cn = element.childNodes().at(m)
                        if status_cn.toElement().tagName() == "state":
                            v.status_state = status_cn.toElement().text()
                elif tag == 'memory':
                    memory = element.text()
                    v.memory = str(int(memory)/1024)
                elif tag == 'cpu':
                    status_c = len(element.childNodes())
                    for m in range(status_c):
                        status_cn = element.childNodes().at(m)
                        if status_cn.toElement().tagName() == "topology":
                            v.cpu_topology_sockets = status_cn.toElement().attribute('sockets')
                            v.cpu_topology_cores = status_cn.toElement().attribute('cores')
                        elif status_cn.toElement().tagName() == "architecture":
                            v.cpu_architecture = status_cn.toElement().text()
                elif tag == 'cpu_shares':
                    v.cpu_shares = element.text()
                elif tag == "display":
                    status_c = len(element.childNodes())
                    for m in range(status_c):
                        status_cn = element.childNodes().at(m)
                        if status_cn.toElement().tagName() == "address":
                            v.display_address = status_cn.toElement().text()
                        if status_cn.toElement().tagName() == "port":
                            v.display_port = status_cn.toElement().text()
                        if status_cn.toElement().tagName() == "secure_port":
                            v.display_secure_port = status_cn.toElement().text()
                elif tag == "os":
                    v.os_type = element.attribute("type")
                    status_c = len(element.childNodes())
                    for m in range(status_c):
                        status_cn = element.childNodes().at(m)
                        if status_cn.toElement().tagName() == "boot":
                            v.os_boot_dev = status_cn.toElement().attribute('dev')
                elif tag == "template":
                    v.template_id = element.attribute("id")
                elif tag == "start_time":
                    stime = element.text()
                    timeList = stime.split("T")
                    time1 = timeList[0]
                    time2 = timeList[1]
                    timeList2 = time2.split(".");
                    qtime = time1 + " " + timeList2[0];
                    v.start_time = qtime
                elif tag == "stop_time":
                    stime = element.text()
                    timeList = stime.split("T")
                    time1 = timeList[0]
                    time2 = timeList[1]
                    timeList2 = time2.split(".");
                    qtime = time1 + " " + timeList2[0];
                    v.stop_time = qtime
                elif tag == "vmpool":
                    v.vmpool_id = element.attribute("id")
                    v.inpool = True
                elif tag == "domain":
                    domain_c = len(element.childNodes())
                    for l in range(domain_c):
                        domain_cn = element.childNodes().at(l)
                        if domain_cn.toElement().tagName() == "name":
                            v.domain_name = domain_cn.toElement().text()
                elif tag == "guest_info":
                    status_c = len(element.childNodes())
                    for m in range(status_c):
                        status_cn = element.childNodes().at(m)
                        if status_cn.toElement().tagName() == "ips":
                            ipscon = len(status_cn.toElement().childNodes())
                            for j in range(ipscon):
                                ip_cn = status_cn.toElement().childNodes().at(j)
                                if ip_cn.toElement().tagName() == "ip":
                                    ip = ip_cn.toElement().attribute("address")
                                    v.guest_info_ips.add(ip)
                # 得到用户的角色：普通用户角色或监视管理员角色
                elif tag == "offlinedesktopavailable":
                    v.offlinedesktopavailable = element.text()
                elif tag == "currentuserrole":
                    userRoleList = [role for role in element.text().split(";") if role]
                    for role in userRoleList:
                        if role in ["MonitorUserRole", "MutiClientUserRole"]:
                            v.permission_id = role
                    if not v.permission_id:
                        v.permission_id = "UserRole"
                elif tag == 'stateless':
                    v.stateless = element.text()
                elif tag == "usetype":
                    v.useType = element.text()
                elif tag == "vm_storagetype":
                    v.vm_storage_type = element.text()
                elif tag == "isCache":
                    #add by p_bc for cache -top
                    v.vm_cache = element.text()
                    #add by p_bc for cache -end
                else:
                    pass
            vmDict[v.id] = v
    
    def __parseDisks(self, vmUUID, dom):
        '''
        @param vmUUID: the uuid of vm 
        @param dom: QDomDocument
        @return: a list of disk class
        '''
        vmDict = VmDict.instance()

        disk_list = dom.elementsByTagName("disk")
        dskCnt = len(disk_list)
        for i in range(dskCnt):
            dsk = Disk()
            node = disk_list.at(i)
            dsk.id = node.toElement().attribute("id")
            itemlist = node.childNodes()
            for j in range(len(itemlist)):
                mynode = itemlist.at(j)
                e = mynode.toElement()
                tag = e.tagName()
                if tag == "name":
                    dsk.name = e.text()
                elif tag == "alias":
                    dsk.alias = e.text()
                elif tag == "image_id":
                    dsk.image_id = e.text()
                elif tag == "size":
                    dsk.size = e.text()
                elif tag == "provisioned_size":
                    dsk.provisioned_size = e.text()
                elif tag == "actual_size":
                    dsk.actual_size = e.text()
                elif tag == 'interface':
                    dsk.interface = e.text()
                elif tag == "bootable":
                    dsk.bootable = e.text()
                else:
                    pass
            vm = vmDict.getVm(vmUUID)
            vm.insertDisk(dsk)
    
    def queryAllVms(self):
        try:
            subUrl = '/massclouds-center/api/vms'
            dom = self._getRequestContext(subUrl)
            #add by p_bc for cache -top
            # print dom.toString(),"this is vms xml.d"
            #add by p_bc for cache -end
            self.__parseVm(dom)
        except Exception, e:
            LogRecord.instance().logger.info(str(e.message))
            raise Exception(str(e.message)) 
    
    def queryVm(self, uuid, vmFlag=True):
        '''
        @uuid: str type
        @vmFlag: True means vm and False means template
        '''
        suburl = ""
        if vmFlag:
            suburl = '/massclouds-center/api/vms/' + uuid
        else:
            suburl = '/massclouds-center/api/templates/' + uuid
        dom = self._getRequestContext(suburl)
        self.__parseVm(dom, vmFlag)
    
    def queryDisk(self, uuid, vmFlag=True):
        '''
        @uuid: vm uuid
        @vmFlag: True means vm, False means template
        '''
        vmDict = VmDict.instance()
        vm = vmDict.getVm(uuid)
        if not vm.disks:
            subUrl = ''
            if vmFlag:
                subUrl = '/massclouds-center/api/vms/' + uuid + '/disks'
            else:
                subUrl = '/massclouds-center/api/templates/' + uuid + '/disks'
            dom = self._getRequestContext(subUrl)
            
            print dom.toString(), "this is net util dom "
            
            self.__parseDisks(uuid, dom)
    
    def queryVmPools(self):
        subUrl = '/massclouds-center/api/vmpools'
        dom = self._getRequestContext(subUrl)
        self.__parseVmPools(dom)
    
    def __parseVmPools(self, dom):
        from common.PoolDict import Pool
        from common.PoolDict import PoolDict
        poolDict = PoolDict.instance()
        poolDict.clear()
        poolList = dom.elementsByTagName("vmpool")
        for i in range(len(poolList)):
            pool = Pool()
            node = poolList.at(i)
            pool.id = node.toElement().attribute("id")
            itemlist = node.childNodes()
            for j in range(len(itemlist)):
                mynode = itemlist.at(j)
                tag = mynode.toElement().tagName()
                text = mynode.toElement().text()
                if tag == "name":
                    pool.name = text
                elif tag == "size":
                    pool.size = text
                elif tag == "prestarted_vms":
                    pool.prestarted_vms = text
                elif tag == 'max_user_vms':
                    pool.max_user_vms = text
                else:
                    pass
            
            poolDict[pool.id] = pool
    
    @classmethod 
    def instance(cls):
        if (cls._instance == None):
            cls._instance = NetUtil()
        return cls._instance
    
