# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements.  See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership.  The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License.  You may obtain a copy of the License at
#
#   http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied.  See the License for the
# specific language governing permissions and limitations
# under the License.



'''Implements the CloudStack API'''


from cloudtool.utils import describe
import urllib.request, urllib.parse, urllib.error
import urllib.request, urllib.error, urllib.parse
import os
import xml.dom.minidom
import re
import base64
import hmac
import hashlib
import http.client

class CloudAPI:

    @describe("server", "Management Server host name or address")
    @describe("apikey", "Management Server apiKey")
    @describe("securitykey", "Management Server securityKey")
    @describe("responseformat", "Response format: xml or json")
    @describe("stripxml", "True if xml tags have to be stripped in the output, false otherwise")
    def __init__(self,
            server="127.0.0.1:8096",
            responseformat="xml",
            stripxml="true",
            apiKey=None,
            securityKey=None
            ):
        self.__dict__.update(locals())

    def _make_request_with_keys(self,command,requests={}):
        requests["command"] = command
        requests["apiKey"] = self.apiKey
        requests["response"] = "xml"
        requests = list(zip(list(requests.keys()), list(requests.values())))
        requests.sort(key=lambda x: str.lower(x[0]))

        requestUrl = "&".join(["=".join([request[0], urllib.parse.quote_plus(str(request[1]))]) for request in requests])
        hashStr = "&".join(["=".join([str.lower(request[0]), urllib.parse.quote_plus(str.lower(str(request[1])))]) for request in requests])

        sig = urllib.parse.quote_plus(base64.encodestring(hmac.new(self.securityKey, hashStr, hashlib.sha1).digest()).strip())

        requestUrl += "&signature=%s"%sig
        return requestUrl


    def _make_request_with_auth(self, command, requests):
        self.connection = http.client.HTTPConnection("%s"%(self.server))
        requests["command"] = command
        requests["apiKey"] = self.apiKey
        requests["response"] = self.responseformat
        requests = list(zip(list(requests.keys()), list(requests.values())))
        requests.sort(key=lambda x: str.lower(x[0]))

        requestUrl = "&".join(["=".join([request[0], urllib.parse.quote(str(request[1],""))]) for request in requests])
        hashStr = "&".join(["=".join([str.lower(request[0]), urllib.parse.quote(str.lower(str(request[1])),"")]) for request in requests])

        sig = urllib.parse.quote_plus(base64.encodestring(hmac.new(self.securityKey, str.lower(hashStr), hashlib.sha1).digest()).strip())

        requestUrl += "&signature=%s"%sig

        self.connection.request("GET", "/client/api?%s"%requestUrl)
        return self.connection.getresponse().read()

    def _make_request(self,command,parameters=None):

        '''Command is a string, parameters is a dictionary'''
        if ":" in self.server:
            host,port = self.server.split(":")
            port = int(port)
        else:
            host = self.server
            port = 8096

        url = "http://" + self.server + "/client/api?"

        if not parameters: parameters = {}
        if self.apiKey is not None and self.securityKey is not None:
            return self._make_request_with_auth(command, parameters)
        else:
            parameters["command"] = command
            parameters["response"] = self.responseformat
            querystring = urllib.parse.urlencode(parameters)

        url += querystring

        f = urllib.request.urlopen(url)
        data = f.read()
        if self.stripxml == "true":
            data=re.sub("<\?.*\?>", "\n", data);
            data=re.sub("</[a-z]*>", "\n", data);
            data=data.replace(">", "=");
            data=data.replace("=<", "\n");
            data=data.replace("\n<", "\n");
            data=re.sub("\n.*cloud-stack-version=.*", "", data);
            data=data.replace("\n\n\n", "\n");

        return data


def load_dynamic_methods():
    '''creates smart function objects for every method in the commands.xml file'''

    def getText(nodelist):
        rc = []
        for node in nodelist:
            if node.nodeType == node.TEXT_NODE: rc.append(node.data)
        return ''.join(rc)

    # FIXME figure out installation and packaging
    xmlfile = os.path.join("/etc/cloud/cli/","commands.xml")
    dom = xml.dom.minidom.parse(xmlfile)

    for cmd in dom.getElementsByTagName("command"):
        name = getText(cmd.getElementsByTagName('name')[0].childNodes).strip()
        assert name

        description = getText(cmd.getElementsByTagName('description')[0].childNodes).strip()
        if description:
                    description = '"""%s"""' % description
        else: description = ''
        arguments = []
        options = []
        descriptions = []

        for param in cmd.getElementsByTagName("request")[0].getElementsByTagName("arg"):
            argname = getText(param.getElementsByTagName('name')[0].childNodes).strip()
            assert argname

            required = getText(param.getElementsByTagName('required')[0].childNodes).strip()
            if required == 'true': required = True
            elif required == 'false': required = False
            else: raise AssertionError("Not reached")
            if required: arguments.append(argname)
            options.append(argname)

                        #import ipdb; ipdb.set_trace()
            requestDescription = param.getElementsByTagName('description')
            if requestDescription:
                descriptionParam = getText(requestDescription[0].childNodes)
            else:
                descriptionParam = ''
            if descriptionParam: descriptions.append( (argname,descriptionParam) )

        funcparams = ["self"] + [ "%s=None"%o for o in options ]
        funcparams = ", ".join(funcparams)

        code = """
        def %s(%s):
            %s
            parms = dict(locals())
            del parms["self"]
            for arg in %r:
                if locals()[arg] is None:
                    raise TypeError, "%%s is a required option"%%arg
            for k,v in parms.items():
                if v is None: del parms[k]
            output = self._make_request("%s",parms)
            return output
        """%(name,funcparams,description,arguments,name)

        namespace = {}
        exec(code.strip(), namespace)

        func = namespace[name]
        for argname,description in descriptions:
            func = describe(argname,description)(func)

        yield (name,func)


for name,meth in load_dynamic_methods():
    setattr(CloudAPI, name, meth)

implementor = CloudAPI

del name,meth,describe,load_dynamic_methods
