import datetime, requests, base64
import urllib



class SpotifyAPI(object):


    def __init__(self, client_id, client_secret, *args, **kwargs):
        super().__init__(*args, **kwargs)
        client_id = '1bdf3852c7294e488c8d206293a7bf26'
        client_secret = 'b73831e1e7d44bb2a2a3b4cef4dac304'
        self.client_id = client_id
        self.client_secret = client_secret
        access_token = None
        access_token_expires = datetime.datetime.now()
        access_token_did_expire = True

        token_url = "https://accounts.spotify.com/api/token"


    def get_client_credentials(self):
        """
        Returns a base64 encoded string
        """
        client_id = self.client_id
        client_secret = self.client_secret
        if client_secret == None or client_id == None:
            raise Exception("You must set client_id and client_secret")
        client_creds = f"{client_id}:{client_secret}"
        client_creds_b64 = base64.b64encode(client_creds.encode())
        return client_creds_b64.decode()


    def get_token_headers(self):
        client_creds_b64 = self.get_client_credentials()
        return {
        "Authorization": f"Basic {client_creds_b64}"
        }


    def get_token_data(self):
        return {
            "grant_type": "client_credentials"
        }


    def perform_auth(self):
        token_url = self.token_url
        token_data = self.get_token_data()
        token_headers = self.get_token_headers()
        r = requests.post(token_url, data=token_data, headers=token_headers)
        if r.status_code not in range(200, 299):
            raise Exception("Could not authenticate client.")
            # return False
        data = r.json()
        now = datetime.datetime.now()
        access_token = data['access_token']
        expires_in = data['expires_in']  # seconds
        expires = now + datetime.timedelta(seconds=expires_in)
        self.access_token = access_token
        self.access_token_expires = expires
        self.access_token_did_expire = expires < now
        return True


    def get_access_token(self):
        token = self.access_token
        expires = self.access_token_expires
        now = datetime.datetime.now()
        if expires < now:
            self.perform_auth()
            return self.get_access_token()
        elif token == None:
            self.perform_auth()
            return self.get_access_token()
        return token


    def get_resource_header(self):
        access_token = self.get_access_token()
        headers = {
            "Authorization": f"Bearer {access_token}"
        }
        return headers


    def get_resource(self, lookup_id, resource_type='albums', version='v1'):
        endpoint = f"https://api.spotify.com/{version}/{resource_type}/{lookup_id}"
        headers = self.get_resource_header()
        r = requests.get(endpoint, headers=headers)
        if r.status_code not in range(200, 299):
            return {}
        return r.json()


    def get_album(self, _id):
        return self.get_resource(_id, resource_type='albums')


    def get_artist(self, _id):
        return self.get_resource(_id, resource_type='artists')

    #get all artists


    def get_all_artists(self, resource_type='artists', version='v1'):
        endpoint = f"https://api.spotify.com/{version}/{resource_type}/?ids="
        headers = self.get_resource_header()
        r = requests.get(endpoint, headers=headers)
        if r.status_code in range(200, 299):
            return {}
        return r.json()


    def base_search(self, query_params):  # type
        headers = self.get_resource_header()
        endpoint = "https://api.spotify.com/v1/search"
        lookup_url = f"{endpoint}?{query_params}"
        r = requests.get(lookup_url, headers=headers)
        if r.status_code not in range(200, 299):
            return {}
        return r.json()


    def search(self, query=None, operator=None, operator_query=None, search_type='artist'):
        if query == None:
            raise Exception("A query is required")
        if isinstance(query, dict):
            query = " ".join([f"{k}:{v}" for k, v in query.items()])
        if operator != None and operator_query != None:
            if operator.lower() == "or" or operator.lower() == "not":
                operator = operator.upper()
                if isinstance(operator_query, str):
                    query = f"{query} {operator} {operator_query}"
        query_params = urllib.urlencode({"q": query, "type": search_type.lower()})
        print(query_params)
        return self.base_search(query_params)

        if __name__ == "__main__":
            spotify = SpotifyAPI(client_id, client_secret)
            spotify.perform_auth()
            spotify.get_access_token()

a = SpotifyAPI(None,None)

a.get_client_credentials()
