import requests
from datetime import datetime
from time import sleep


class RateLimitException(Exception):
    pass

class RiotAPIException(Exception):
    def __init__(self, status_code, url):
        self.status_code = status_code
        self.url = url

    def __str__(self):
        return 'Invalid request.  Status Code: ' + str(self.status_code)+ '\n' + self.url

class MatchNotFoundException(Exception):
    def __init__(self, match_id):
        self.match_id = match_id

    def __str__(self):
        return "Match " + self.match_id + ' is invalid.'

class RiotAPI(object):

    def __init__(self, api_key, region = 'na'):
        self._baseurl = 'https://'+region+'.api.pvp.net/api/lol/na/v2.2/'
        self._staticUrl = 'https://global.api.pvp.net/api/lol/static-data/' + region + '/v1.2/'
        self._last_request = datetime(1900, 1, 1)
        self._api_key = api_key
        self._session = requests.Session()
        self._session.params = { 'api_key': self._api_key }

    def _process_response(self, resp):
        if(resp.status_code == 200):
            return resp.json()  
        elif(resp.status_code == 429):
            raise RateLimitException()
        else:
            raise RiotAPIException(resp.status_code, resp.url)

    def _check_rate_limit(self):
        since_last_request = (datetime.now() - self._last_request).total_seconds()
        next_request_in = 1.2 - since_last_request
        if(next_request_in > 0):
            sleep(next_request_in)

        self._last_request = datetime.now()

    def _make_request(self, url, params = {}):
        self._check_rate_limit()
        
        r = self._session.get(url, params=params)
        return self._process_response(r)

    def matchlist(self, summoner_id):
        return self._make_request(self._baseurl + 'matchlist/by-summoner/'+summoner_id)


    def match(self, match_id, include_timeline=True):
        params = {
            'includeTimeline' : include_timeline
        }        
        try :
            return self._make_request(self._baseurl + 'match/'+match_id, params)
        except RiotAPIException as e:
            if(e.status_code == 404):
                raise MatchNotFoundException(match_id)
            else:
                raise e

    def champion(self, champData=None, dataById=False, version=None, locale='en_US', championId = None):
        params = {
            'champData' : champData,
            'dataById' : dataById,
            'version' : version,
            'locale' : locale
        }

        url = self._staticUrl + 'champion'

        if(championId is not None):
            url = url + '/' + championId

        return self._make_request(url, params)

    def item(self, itemListData=None, version=None, locale='en_US', itemId = None):
        params = {
            'itemListData' : itemListData,
            'version' : version,
            'locale' : locale
        }

        url = self._staticUrl + 'item'

        if(itemId is not None):
            url = url + '/' + itemId

        return self._make_request(url, params)


