# 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.

import base64
import hashlib
import copy
import hmac

from libcloud.utils.py3 import httplib
from libcloud.utils.py3 import urlencode
from libcloud.utils.py3 import urlquote
from libcloud.utils.py3 import b

from libcloud.common.types import ProviderError
from libcloud.common.base import ConnectionUserAndKey, PollingConnection
from libcloud.common.base import JsonResponse
from libcloud.common.types import MalformedResponseError
from libcloud.compute.types import InvalidCredsError


class CloudStackResponse(JsonResponse):
    def parse_error(self):
        if self.status == httplib.UNAUTHORIZED:
            raise InvalidCredsError("Invalid provider credentials")

        value = None
        body = self.parse_body()
        if hasattr(body, "values"):
            values = list(body.values())[0]
            if "errortext" in values:
                value = values["errortext"]
        if value is None:
            value = self.body

        if not value:
            value = "WARNING: error message text sent by provider was empty."

        error = ProviderError(
            value=value, http_code=self.status, driver=self.connection.driver
        )
        raise error


class CloudStackConnection(ConnectionUserAndKey, PollingConnection):
    responseCls = CloudStackResponse
    poll_interval = 1
    request_method = "_sync_request"
    timeout = 600

    ASYNC_PENDING = 0
    ASYNC_SUCCESS = 1
    ASYNC_FAILURE = 2

    def encode_data(self, data):
        """
        Must of the data is sent as part of query params (eeww),
        but in newer versions, userdata argument can be sent as a
        urlencoded data in the request body.
        """
        if data:
            data = urlencode(data)

        return data

    def _make_signature(self, params):
        signature = [(k.lower(), v) for k, v in list(params.items())]
        signature.sort(key=lambda x: x[0])

        pairs = []
        for pair in signature:
            key = urlquote(str(pair[0]), safe="[]")
            value = urlquote(str(pair[1]), safe="[]*")
            item = "%s=%s" % (key, value)
            pairs.append(item)

        signature = "&".join(pairs)

        signature = signature.lower().replace("+", "%20")
        signature = hmac.new(b(self.key), msg=b(signature), digestmod=hashlib.sha1)
        return base64.b64encode(b(signature.digest()))

    def add_default_params(self, params):
        params["apiKey"] = self.user_id
        params["response"] = "json"

        return params

    def pre_connect_hook(self, params, headers):
        params["signature"] = self._make_signature(params)

        return params, headers

    def _async_request(
        self,
        command,
        action=None,
        params=None,
        data=None,
        headers=None,
        method="GET",
        context=None,
    ):
        if params:
            context = copy.deepcopy(params)
        else:
            context = {}

        # Command is specified as part of GET call
        context["command"] = command
        result = super(CloudStackConnection, self).async_request(
            action=action,
            params=params,
            data=data,
            headers=headers,
            method=method,
            context=context,
        )
        return result["jobresult"]

    def get_request_kwargs(
        self, action, params=None, data="", headers=None, method="GET", context=None
    ):
        command = context["command"]
        request_kwargs = {
            "command": command,
            "action": action,
            "params": params,
            "data": data,
            "headers": headers,
            "method": method,
        }
        return request_kwargs

    def get_poll_request_kwargs(self, response, context, request_kwargs):
        job_id = response["jobid"]
        params = {"jobid": job_id}
        kwargs = {"command": "queryAsyncJobResult", "params": params}
        return kwargs

    def has_completed(self, response):
        status = response.get("jobstatus", self.ASYNC_PENDING)

        if status == self.ASYNC_FAILURE:
            msg = response.get("jobresult", {}).get("errortext", status)
            raise Exception(msg)

        return status == self.ASYNC_SUCCESS

    def _sync_request(
        self, command, action=None, params=None, data=None, headers=None, method="GET"
    ):
        """
        This method handles synchronous calls which are generally fast
        information retrieval requests and thus return 'quickly'.
        """
        # command is always sent as part of "command" query parameter
        if params:
            params = copy.deepcopy(params)
        else:
            params = {}

        params["command"] = command
        # pylint: disable=maybe-no-member
        result = self.request(
            action=self.driver.path,
            params=params,
            data=data,
            headers=headers,
            method=method,
        )

        command = command.lower()

        # Work around for older verions which don't return "response" suffix
        # in delete ingress rule response command name
        if (
            command == "revokesecuritygroupingress"
            and "revokesecuritygroupingressresponse" not in result.object
        ):
            command = command
        elif (
            command == "restorevirtualmachine" and "restorevmresponse" in result.object
        ):
            command = "restorevmresponse"
        else:
            command = command + "response"

        if command not in result.object:
            raise MalformedResponseError(
                "Unknown response format {}".format(command),
                body=result.body,
                driver=self.driver,
            )
        result = result.object[command]
        return result


class CloudStackDriverMixIn(object):
    host = None
    path = None

    connectionCls = CloudStackConnection

    def __init__(self, key, secret=None, secure=True, host=None, port=None):
        host = host or self.host
        super(CloudStackDriverMixIn, self).__init__(key, secret, secure, host, port)

    def _sync_request(
        self, command, action=None, params=None, data=None, headers=None, method="GET"
    ):
        return self.connection._sync_request(
            command=command,
            action=action,
            params=params,
            data=data,
            headers=headers,
            method=method,
        )

    def _async_request(
        self,
        command,
        action=None,
        params=None,
        data=None,
        headers=None,
        method="GET",
        context=None,
    ):
        return self.connection._async_request(
            command=command,
            action=action,
            params=params,
            data=data,
            headers=headers,
            method=method,
            context=context,
        )
