"""Module for parent RawWrapper class"""

import os
import json
import simplejson
import requests
from typing import Union

from .errors import MalformedDataError


class RawWrapper:
    """Builds, and makes requests to the API"""

    def __init__(self, api_url: str, token: str) -> None:
        """Prepares and stores API URL and Love Lived Access Token token"""
        self.api_url = api_url
        if not self.api_url.endswith('/'):
            self.api_url += '/'
        self._token = token

    def endpoint(self, path: str) -> str:
        """Joins the api base url with a local path to an absolute url"""
        url = os.path.join(self.api_url, path)
        return url

    @property
    def _headers(self) -> dict:
        """Constructs the headers to send to the api for every request"""
        return {
            "Authorization": f"Bearer {self._token}",
            "content-type": "application/json",
        }

    def request(
        self,
        path,
        method='GET',
        headers: dict = None,
        return_text_if_fail=False,
        **kwargs
    ) -> Union[dict, list, str]:
        """Base method for making requests to the api"""
        if headers is None:
            headers = {}
        if isinstance(headers, dict):
            headers.update(self._headers)
        else:
            raise ValueError(f'headers must be dict or dict subclass, not type "{type(headers).__name__}"')

        resp = requests.request(
            method,
            self.endpoint(path),
            headers=headers,
            **kwargs
        )
        return self.response_logic(resp, return_text_if_fail)

    def response_logic(self, response: requests.Response, return_text_if_fail=False) -> Union[dict, list, str]:
        """Processes reponses from the api and formats them"""
        try:
            res = response.json()
        except (json.decoder.JSONDecodeError, simplejson.decoder.JSONDecodeError):
            if return_text_if_fail:
                return response.text
            else:
                raise MalformedDataError(f'Homeassistant responded with non-json response: {repr(response.text)}')
        else:
            return res

    def construct_params(self, params: dict) -> str:
        """Custom method for constructing non-standard query strings"""
        return '&'.join([
            k if v is None
            else f"{k}={v}"
            for k, v in params.items()
        ])
