# -*- coding: utf-8 -*-

from PyQt4.QtCore import QObject
import requests
import json
from common.commondata import authFailMsg
from model.infomodel.userinfo import LoginUserInfo


class HttpRequests(QObject):
    _instance = 0
    def __init__(self):
        super(HttpRequests,self).__init__()
        self.headers = {
                        'Host': 'identity.api.openstack.org',
                        'Content-Type': 'application/json',
                        'Accept': 'application/json',
                        'Accept-Encoding': 'gzip, deflate',
                        'Accept-Language': 'en-US,en;q=0.5',
                        'Cookie': 'username=root; kimchiLang=zh_CN',
                        'X-Requested-With': 'XMLHttpRequest',
                                }
        self.currentTenantName = ""
        self.openstackServiceHostMap = {}

    def setOpenstackServiceHost(self, accessInfo):
        if not accessInfo:
            return
        
        if accessInfo.get("access", None) is None:
            return
        
        if accessInfo["access"].get("serviceCatalog", None) is None:
            return
        
        endPoints = accessInfo["access"]["serviceCatalog"]
        for subEndPoint in endPoints:
            if subEndPoint.get("endpoints", None) is None:
                continue
            
            for url in subEndPoint["endpoints"]:
                adminURL = url["adminURL"]
                address = adminURL.split(":")[1][2:]
                port = adminURL.split(":")[2].split('/')[0]
                self.openstackServiceHostMap[port] = address
        
        

    def getAuthToken(self, tenantName):
        """
        获取认证
        """
        userInfo = LoginUserInfo.instance().getUserInfo()
        urlPath = "http://%s:5000/v2.0/tokens" % userInfo.serverIp
        payload = {
                    "auth": {
                        "tenantName": tenantName,
                        "passwordCredentials": {
                            "username": userInfo.name,
                            "password": userInfo.password,
                                                                }
                                    }
                        }
        
        try:
            r = requests.post(urlPath, data=json.dumps(payload), headers=self.headers)
            if r.ok:
                self.currentTenantName = tenantName
                infoDict = r.json()
                self.setOpenstackServiceHost(infoDict)
                self.headers.update({'X-Auth-Token': infoDict["access"]["token"]["id"]})
                return infoDict
        except requests.exceptions.ConnectionError, e:
                return "ConnectionError"
        
        return None


    def getServiceURL(self, url):
        userInfo = LoginUserInfo.instance().getUserInfo()   
        if not url:
            address = "http://" + userInfo.serverIp + ":"
            return address + url
        
        port = url.split("/")[0]
        hostAddress = self.openstackServiceHostMap.get(port, None)
        if hostAddress is None:
            address = "http://" + userInfo.serverIp + ":"
            return address + url
        
        return "http://" + hostAddress + ":" + url
        

    def getRequestInfo(self, url, tenantName):
        """
        获取请求的信息
        @url 请求的url信息
        """
        try:
            if not self.currentTenantName or self.currentTenantName != tenantName:
                value = self.getAuthToken(tenantName)
                if value is None or value == "ConnectionError":
                    return value
                
                newUrl = self.getServiceURL(url)
                request = requests.get(newUrl, headers=self.headers)
            else:
                
                newUrl = self.getServiceURL(url)
                request = requests.get(newUrl, headers=self.headers)
                if not request.ok and request.content == authFailMsg:
                    value = self.getAuthToken(tenantName)
                    if value is None or value == "ConnectionError":
                        return value
                    
                    request = requests.get(self.getServiceURL(url), headers=self.headers)
                    
            if request.ok:
                return request.json()
            elif request.status_code == 403:
                return "forbidden"
            else:
                return None
        
        except requests.exceptions.ConnectionError, e:
                return None
        
        return None
        
    def postRequestInfo(self, url, info, tenantName, isNeedReturnValue=False):
        """
        执行相应的请求操作
        @url 请求的url信息，
        @info 执行操作时需要的数据
        @isNeedReturnValue 执行完操作时，是否需要返回相应的信息
        """
        try:
            if not self.currentTenantName or self.currentTenantName != tenantName:
                value = self.getAuthToken(tenantName)
                if value is None or value == "ConnectionError":
                    return value
                
                request = requests.post(self.getServiceURL(url), data=json.dumps(info), headers=self.headers)
            else:
                request = requests.post(self.getServiceURL(url), data=json.dumps(info), headers=self.headers)
                if not request.ok and request.content == authFailMsg:
                    value = self.getAuthToken(tenantName)
                    if value is None or value == "ConnectionError":
                        return value
                    
                    request = requests.post(self.getServiceURL(url), data=json.dumps(info), headers=self.headers)
            
            if request.status_code == 403:
                return "forbidden"
                
            if request.ok and isNeedReturnValue:
                return request.json()
            
            if request.ok and not isNeedReturnValue:
                return True
        except requests.exceptions.ConnectionError, e:
                return False
            
        return False
            
    def putRequestInfo(self, url, info, tenantName, isNeedReturnValue=False):
        try:
            if not self.currentTenantName or self.currentTenantName != tenantName:
                value = self.getAuthToken(tenantName)
                if value is None or value == "ConnectionError":
                    return value
                
                request = requests.put(self.getServiceURL(url), data=json.dumps(info), headers=self.headers)
            else:
                request = requests.put(self.getServiceURL(url), data=json.dumps(info), headers=self.headers)
                if not request.ok and request.content == authFailMsg:
                    value = self.getAuthToken(tenantName)
                    if value is None or value == "ConnectionError":
                        return value
                    
                    request = requests.put(self.getServiceURL(url), data=json.dumps(info), headers=self.headers)
                
            if request.status_code == 403:
                return "forbidden"
            
            if request.ok and isNeedReturnValue:
                return request.json()
            
            if request.ok and not isNeedReturnValue:
                return True
            
            
        except requests.exceptions.ConnectionError, e:
                return False
            
        return False
        
            
    def postRequestInfo_(self, url, info, tenantName, isNeedReturnValue=False):
        """
        执行相应的请求操作
        @url 请求的url信息，
        @info 执行操作时需要的数据
        @isNeedReturnValue 执行完操作时，是否需要返回相应的信息
        """
        try:
            value = self.getAuthToken(tenantName)
            if value is None or value == "ConnectionError":
                return value
            
            request = requests.post(self.getServiceURL(url), data=json.dumps(info), headers=self.headers)
            if request.ok and isNeedReturnValue:
                return request.json()
            
            if request.ok and not isNeedReturnValue:
                return True
        except requests.exceptions.ConnectionError, e:
                return False
            
        return False

 
        
        
        