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

"""
Common settings and connection objects for gridscale
"""

try:
    import simplejson as json
except Exception:
    import json  # type: ignore

from libcloud.utils.py3 import httplib
from libcloud.common.base import BaseDriver, JsonResponse, PollingConnection, ConnectionUserAndKey
from libcloud.common.types import InvalidCredsError
from libcloud.compute.types import NodeState

NODE_STATE_MAP = {
    "ACTIVE": NodeState.RUNNING,
    "STOPPED": NodeState.STOPPED,
    "UNKNOWN": NodeState.UNKNOWN,
}


class GridscaleResponse(JsonResponse):
    """
    Gridscale API Response
    """

    valid_response_codes = [httplib.OK, httplib.ACCEPTED, httplib.NO_CONTENT]

    def parse_error(self):
        body = self.parse_body()
        if self.status == httplib.UNAUTHORIZED:
            raise InvalidCredsError(body["message"])
        if self.status == httplib.NOT_FOUND:
            raise Exception("The resource you are looking for has not been found.")
        return self.body

    def success(self):
        return self.status in self.valid_response_codes


class GridscaleConnection(ConnectionUserAndKey, PollingConnection):
    """
    gridscale connection class
    Authentication using uuid and api token

    """

    host = "api.gridscale.io"
    responseCls = GridscaleResponse

    def encode_data(self, data):
        return json.dumps(data)

    def add_default_headers(self, headers):
        """
        add parameters that are necessary for each request to be successful

        :param headers: Authentification token
        :type headers: ``str``
        :return: None
        """
        headers["X-Auth-UserId"] = self.user_id
        headers["X-Auth-Token"] = self.key
        headers["Content-Type"] = "application/json"

        return headers

    def async_request(self, *poargs, **kwargs):
        self.async_request_counter = 0
        self.request_method = "_poll_request_initial"
        return super().async_request(*poargs, **kwargs)

    def _poll_request_initial(self, **kwargs):
        if self.async_request_counter == 0:
            self.poll_response_initial = super().request(**kwargs)
            r = self.poll_response_initial
            self.async_request_counter += 1
        else:
            r = self.request(**kwargs)

        return r

    def get_poll_request_kwargs(self, response, context, request_kwargs):

        endpoint_url = "requests/{}".format(response.object["request_uuid"])
        kwargs = {"action": endpoint_url}
        return kwargs

    def has_completed(self, response):
        if response.status == 200:
            request_uuid = self.poll_response_initial.object["request_uuid"]
            request_status = response.object[request_uuid]["status"]
            if request_status == "done":
                return True
        return False


class GridscaleBaseDriver(BaseDriver):
    name = "gridscale"
    website = "https://gridscale.io"
    connectionCls = GridscaleConnection

    def __init__(self, user_id, key, **kwargs):
        super().__init__(user_id, key, **kwargs)

    def _sync_request(self, data=None, endpoint=None, method="GET"):
        raw_result = self.connection.request(endpoint, data=data, method=method)

        return raw_result
