import json
import aiohttp
from .interfaces import *


class APIService():
    def __init__(self, url, UUID=""):
        self.server_url = url
        self.auth_token = None
        self.api_token = None
        self.uuid = UUID
        self.client = aiohttp.ClientSession()

    async def close_session(self):
        if self.client is not None:
            return await self.client.close()

    async def get(self, service_url, query={}, auth_required=False):
        """
            Makes a GET request and returns the results
            Inputs:
                - service_url(str): the url to make the request to.
                - query(dict): the get query.
                - auth_required(bool): indicates whether authorization is required for the call or not.
        """
        url = self._create_url(service_url)

        response = None
        if auth_required:
            response = await self.client.get(
                url,
                params=query,
                headers={
                    'Authorization': 'Bearer {}'.format(self.auth_token) if self.auth_token else '',
                    'x-api-token': self.api_token or '',
                    'x-mm-id': self.uuid or ''

                }
            )
        else:
            response = await self.client.get(url, params=query)

        try:
            if response.status != 503:  # checking for service unavailitbility
                return await response.json()
            else:
                return response
        except:
            raise Exception("Error while getting {}: {}".format(url, response))

    async def post(self, service_url, data, auth_required=False, contentType=""):
        """
            Makes a POST request and returns the results
            Inputs:
                - service_url(str): the url to make the request to.
                - data(dict): the data to post with POST request.
                - auth_required(bool): indicates whether authorization is required for the call or not.
        """
        url = self._create_url(service_url)
        response = None
        if auth_required:
            headers = {
                'Authorization': 'Bearer {}'.format(self.auth_token),
                'x-mm-id': self.uuid or ''
            }

            if contentType is not "":
                headers['Content-type'] = contentType

            response = await self.client.post(url=url, data=data, headers=headers)
        else:
            response = await self.client.post(url=url, data=data)

        try:
            if response.status != 503:  # checking for service unavailitbility
                return await response.json()
            else:
                return response
        except:
            raise Exception(
                "Error while posting to {}: {}".format(url, response))

    async def delete(self, service_url, data, auth_required=False):
        """
            Makes a DELETE request and returns the results
            Inputs:
                - service_url(str): the url to make the request to.
                - data(dict): the data to post with POST request.
                - auth_required(bool): indicates whether authorization is required for the call or not.
        """
        url = self._create_url(service_url)

        response = None
        if auth_required:
            response = await self.client.delete(
                url=url,
                data=data,
                headers={'Authorization': 'Bearer {}'.format(self.auth_token),
                 'x-mm-id': self.uuid or ''})
        else:
            response = await self.client.delete(url=url, data=data)

        try:
            return await response.json()
        except:
            raise Exception(
                "Error while posting to {}: {}".format(url, response))

    '''
        Private methods
    '''

    def _create_url(self, path):
        """
            Appends namespace to server url
        """
        return "{}{}".format(self.server_url, path)
